turbo-design 1.0.10__py3-none-any.whl → 1.1.0__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.1
1
+ Metadata-Version: 2.3
2
2
  Name: turbo-design
3
- Version: 1.0.10
3
+ Version: 1.1.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
@@ -1,6 +1,6 @@
1
1
  turbodesign/__init__.py,sha256=N8Nu0I1vrlEHYJZZ7yhhg-FtbNbLyrgjy7hoicygUqg,325
2
2
  turbodesign/arrayfuncs.py,sha256=GHIlTyLfeNsNCQQoh5m1aXK3iyvU6RjdYQipkqpU_ps,519
3
- turbodesign/bladerow.py,sha256=F94KAARzGd4edOgs2Cd6dSRteyYCR5U45687anYY-As,24042
3
+ turbodesign/bladerow.py,sha256=-Oym4HhX9Wx6i6Nv7Krb6xdZWSxLiEVMb7xg2K5rR0w,24239
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=nuj7ryUXuBhuOPt2jHjHwtEM_LVno7A8Wm14P0lJn-8,436
@@ -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=9cRSCZIS4LqlIcO8mOeePN42hmcc4g8tFDZ3F86WM7E,7594
24
- turbodesign/radeq.py,sha256=4unpFad6hvgaYwYLBNI8o9bszyvoNiizYjMqRX0Mjcc,10012
23
+ turbodesign/passage.py,sha256=eZGaB5Gq9Frm80TTDJaLm1TxJV2-_fHHIeqjPuvtb8E,9550
24
+ turbodesign/radeq.py,sha256=RCsiQzcHvR5dozK6XG0eysAhXYewF0BY_qX0f1knURo,10091
25
25
  turbodesign/rotor.py,sha256=tHl9o5H4aQ6Etd4gqa8Ime1UK7k0de4GLt5Yb1sJdGs,1376
26
26
  turbodesign/solve_radeq.py,sha256=2VGzFSVkyN0rTPFHaCQiD3v166cdEs39x7x7RuzLgmw,1886
27
- turbodesign/spool.py,sha256=FImXUwB4bJSAFroae-Y0fL5T7hBCiHg17Uo2zRvcFnA,13864
27
+ turbodesign/spool.py,sha256=h4m--HR5g8o01Kkhl4Mbvx7WORQez3YpncDE7XxbNaw,14172
28
28
  turbodesign/stage.py,sha256=UP45sDKDLsAkO_WfDWJ6kqXU7cYKh_4QO01QZnSN1oQ,166
29
- turbodesign/td_math.py,sha256=28cGzmTMs2evC0vMEp0oN6UmSJDHsKfXw51XJSMxmo8,17370
30
- turbodesign/turbinespool.py,sha256=s9cZpK9245pjUYI5hOo81SsO8UqG-TVUJlSN7SQu7yw,25877
31
- turbo_design-1.0.10.dist-info/METADATA,sha256=jQ5YdRxxq3NcYV-B7beGfmgTGTsGhMzE8PC8Y3W23QU,684
32
- turbo_design-1.0.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
33
- turbo_design-1.0.10.dist-info/RECORD,,
29
+ turbodesign/td_math.py,sha256=K_LyxcgDWNjR9vOA4wfofzlmJlsDn_y64Rj1wi0FTZo,17489
30
+ turbodesign/turbinespool.py,sha256=OJZsucQpGiAHSQOmi7FcagN3jP8dai8umtwC0jBVZGM,25959
31
+ turbo_design-1.1.0.dist-info/METADATA,sha256=feg_7pDPWUK07MJJR8jhx8g6ixlSiEZerhcdKJQ9GBk,734
32
+ turbo_design-1.1.0.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
33
+ turbo_design-1.1.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.0.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
turbodesign/bladerow.py CHANGED
@@ -117,7 +117,7 @@ class BladeRow:
117
117
  _te_s:float = 0.08
118
118
  _tip_clearance:float = 0 # Clearance as a percentage of span or blade height
119
119
 
120
- _inlet_to_outlet_pratio = [0.06,0.7]
120
+ _inlet_to_outlet_pratio = [0.06,0.95]
121
121
 
122
122
  @property
123
123
  def inlet_to_outlet_pratio(self) -> Tuple[float,float]:
@@ -432,7 +432,10 @@ class BladeRow:
432
432
  val (float): new trailing edge to pitch ratio
433
433
  """
434
434
  self._te_s = val
435
-
435
+
436
+ def __repr__(self):
437
+ 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"
438
+
436
439
  def to_dict(self):
437
440
 
438
441
  data = {
turbodesign/passage.py CHANGED
@@ -104,26 +104,42 @@ class Passage:
104
104
 
105
105
  """
106
106
  phi = np.zeros(shape=x_streamline.shape)
107
- rm = phi.copy()
108
- r = phi.copy()
109
-
110
- d_dx = FinDiff(0,x_streamline,1)
111
- d2_dx2 = FinDiff(0,x_streamline,2)
112
- dr_dx = d_dx(r_streamline)
113
- d2r_dx2 = d2_dx2(r_streamline)
107
+ r = np.zeros(shape=x_streamline.shape)
108
+ radius_curvature = np.zeros(shape=x_streamline.shape)
109
+ # Have to make sure there isn't a divide by zero which could happen if there is a vertical line somewhere
110
+ indices = np.where(np.abs(np.diff(x_streamline))>np.finfo(float).eps)[0]
111
+
112
+ d_dx = FinDiff(0,x_streamline[indices[0]:indices[-1]],1)
113
+ d2_dx2 = FinDiff(0,x_streamline[indices[0]:indices[-1]],2)
114
+ dr_dx = d_dx(r_streamline[indices[0]:indices[-1]])
115
+ d2r_dx2 = d2_dx2(r_streamline[indices[0]:indices[-1]])
114
116
 
115
- radius_curvature = np.power((1+np.power(dr_dx,2)),1.5)
116
- radius_curvature = np.divide(radius_curvature, np.abs(d2r_dx2))
117
+ radius_curvature[indices[0]:indices[-1]] = np.power((1+np.power(dr_dx,2)),1.5)
118
+ radius_curvature[indices[0]:indices[-1]] = np.divide(radius_curvature[indices[0]:indices[-1]], np.abs(d2r_dx2))
117
119
  radius_curvature = np.nan_to_num(radius_curvature,nan=0)
118
120
 
121
+ def vertical_line_phi(start:int,end:int):
122
+ # Lets get the phi and slope for the vertical parts
123
+ for i in range(start,end):
124
+ dx = x_streamline[i] - x_streamline[i-1]
125
+ dr = r_streamline[i] - r_streamline[i-1]
126
+ if (dr < 0) & (np.abs(dx) < np.finfo(float).eps):
127
+ phi[i-1] = -np.pi/2
128
+ elif (dr > 0) & (np.abs(dx) < np.finfo(float).eps):
129
+ phi[i-1] = np.pi/2
130
+ radius_curvature[i-1] = 1000000 # Initialize to high number, used in radeq.
131
+
132
+ vertical_line_phi(1,indices[0])
133
+ vertical_line_phi(indices[1],len(x_streamline))
134
+
119
135
  rm = radius_curvature # https://www.cuemath.com/radius-of-curvature-formula/ should be 1/curvature
120
- phi = np.arctan(dr_dx)
136
+ phi[indices[0]:indices[-1]] = np.arctan(dr_dx)
121
137
  r = r_streamline
122
138
 
123
139
  return phi, rm, r
124
140
 
125
141
  def get_cutting_line(self, t_hub:float) -> line2D:
126
- """Gets the cutting line between hub and shroud
142
+ """Gets the cutting line perpendicular to hub and shroud
127
143
 
128
144
  Args:
129
145
  t_hub (float): percentage along the axial direction
@@ -168,6 +184,27 @@ class Passage:
168
184
  rshroud = self.rshroud(t_shroud)
169
185
  return line2D([xhub,rhub],[xshroud,rshroud]), t_hub, t_shroud
170
186
 
187
+ def get_xr_slice(self,t_span:float,axial_location:float):
188
+ """Returns the xr coordinates of a streamline, a line that is parallel to both hub and shroud
189
+
190
+ Args:
191
+ t_span (float): _description_
192
+ axial_location (float): _description_
193
+
194
+ Returns:
195
+ np.NDArray: _description_
196
+ """
197
+ t_hub = np.linspace(0,axial_location,100)
198
+
199
+ shroud_pts_cyl = np.vstack([self.xshroud(t_hub),self.rshroud(t_hub)]).transpose()
200
+ hub_pts_cyl = np.vstack([self.xhub(t_hub),self.rhub(t_hub)]).transpose()
201
+ n = len(t_hub)
202
+
203
+ xr = np.zeros((n,2))
204
+ for j in range(n):
205
+ l = line2D(hub_pts_cyl[j,:],shroud_pts_cyl[j,:])
206
+ xr[j,0],xr[j,1] = l.get_point(t_span)
207
+ return xr
171
208
 
172
209
  @property
173
210
  def hub_length(self):
@@ -186,7 +223,7 @@ class Passage:
186
223
 
187
224
  plt.figure(num=1,clear=True,dpi=150,figsize=(15,10))
188
225
  plt.plot(self.xhub_pts,self.rhub_pts,label='hub',linestyle='solid',linewidth=2,color='black')
189
- plt.plot(self.xshroud_pts,self.rshroud_pts,label='hub',linestyle='solid',linewidth=2,color='black')
226
+ plt.plot(self.xshroud_pts,self.rshroud_pts,label='shroud',linestyle='solid',linewidth=2,color='black')
190
227
  for p in percent_axial:
191
228
  cut,_,_ = self.get_cutting_line(p)
192
229
  x,r = cut.get_point(np.linspace(0,1,10))
turbodesign/radeq.py CHANGED
@@ -52,12 +52,12 @@ def radeq(row:BladeRow,upstream:BladeRow) -> BladeRow:
52
52
  gamma = row.gamma
53
53
 
54
54
  # Solve the Radial Equlibrium
55
- Vt = Vm*np.cos(phi)*np.tan(alpha)
55
+ Vt = Vm*np.tan(alpha)
56
56
  Vr = Vm*np.sin(phi)
57
57
  # Estimations
58
58
  dVm_dr = float(interp1d(row_radius, np.gradient(row.Vm, row_radius))(r))
59
- dVt_dr = dVm_dr*np.cos(phi)*np.tan(alpha)
60
- dVr_dr = 0 #dVm_dr*np.sin(phi)
59
+ dVt_dr = dVm_dr*np.tan(alpha)
60
+ dVr_dr = dVm_dr*np.sin(phi)
61
61
 
62
62
  # Upstream
63
63
  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
@@ -74,7 +74,9 @@ def radeq(row:BladeRow,upstream:BladeRow) -> BladeRow:
74
74
  # if row.loss_function.LossType == LossType.Pressure: # type: ignore
75
75
  # dP0_dr = dP0up_dr-row.Yp*(dP0up_dr - dP_dr) # Eqn 9
76
76
 
77
- C = Vm**2*(1+np.cos(phi)**2 * np.tan(alpha)**2)/(2*Cp*T0)
77
+ C = Vm**2*(1+np.tan(alpha)**2)/(2*Cp*T0)
78
+ if (C>1) & ((gamma/(gamma-1))<2):
79
+ raise Exception("Invalid value of C {C}, change reduce alpha or Vm")
78
80
  B = (1-C)**(gamma/(gamma-1))
79
81
  A = P0 * gamma/(gamma-1) * (1-C)**(1/(gamma-1))
80
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
turbodesign/spool.py CHANGED
@@ -87,6 +87,8 @@ class Spool:
87
87
  new_gas (ct.Solution.Solution): New gas mixture
88
88
  """
89
89
  self._fluid = newFluid
90
+ for i in range(len(self.blade_rows)):
91
+ self.blade_rows[i].fluid = self.fluid
90
92
 
91
93
  @property
92
94
  def adjust_streamlines(self) -> bool:
@@ -249,7 +251,7 @@ class Spool:
249
251
  plt.figure(num=1,clear=True)
250
252
  for i in range(1,len(self.blade_rows)-1): # Don't plot inlet or outlet
251
253
  row = self.blade_rows[i]
252
- x_end = x_start + row.Vx.mean()
254
+ x_end = x_start + row.Vm.mean()
253
255
  dx = x_end - x_start
254
256
 
255
257
  Vt = row.Vt[j]
@@ -285,9 +287,15 @@ class Spool:
285
287
  plt.annotate("", xy=(x_end,Wt+U), xytext=(x_end,Wt), arrowprops=prop) # U
286
288
  plt.text(x_end+dx*0.1,Wt+U/2,"U",fontdict={"fontsize":"xx-large"})
287
289
 
288
- plt.text((x_start+x_end)/2,-y_max*0.95,row.row_type.name,fontdict={"fontsize":"xx-large"})
289
- x_start += row.Vx[j]
290
+ if -np.sign(Vt)>0:
291
+ y = y_min
292
+ else:
293
+ y = y_max
294
+ plt.text((x_start+x_end)/2,-np.sign(Vt)*y*0.95,row.row_type.name,fontdict={"fontsize":"xx-large"})
295
+ x_start += row.Vm[j]
290
296
  plt.axis([0,x_end+dx, y_min, y_max])
297
+ plt.ylabel("Tangental Velocity [m/s]")
298
+ plt.xlabel("Vm [m/s]")
291
299
  plt.title(f"Velocity Triangles for Streamline {j}")
292
300
  plt.savefig(f"streamline_{j:04d}.png",transparent=False,dpi=150)
293
301
 
turbodesign/td_math.py CHANGED
@@ -4,6 +4,7 @@ import math
4
4
  import numpy.typing as npt
5
5
  from .bladerow import BladeRow, compute_gas_constants
6
6
  from .enums import RowType, LossType
7
+ from scipy.integrate import trapezoid
7
8
 
8
9
  def T0_coolant_weighted_average(row:BladeRow) -> float:
9
10
  """Calculate the new weighted Total Temperature array considering coolant
@@ -99,7 +100,7 @@ def compute_power(row:BladeRow,upstream:BladeRow) -> None:
99
100
  row.eta_static = row.power/ (row.massflow[-1]*row.Cp*(upstream.T0.mean()-row.T0_is.mean()))
100
101
  row.eta_total = row.power / (row.massflow[-1]*row.Cp * (upstream.T0.mean()-row.T0_is.mean()))
101
102
  row.stage_loading = row.Cp*(upstream.T0.mean() - row.T0.mean())/row.U.mean()**2
102
- row.euler_power = (row.massflow[-1]*((row.U+upstream.U)/2).mean()*(upstream.Vt-row.Vt).mean())
103
+ row.euler_power = row.massflow[-1]* (upstream.U*upstream.Vt - row.U*row.Vt).mean()
103
104
 
104
105
  def compute_quantities(row:BladeRow,upstream:BladeRow):
105
106
  """Calculation of all quantites after radial equilibrium has been solved assuming we know the static pressure at the exit.
@@ -254,21 +255,18 @@ def stator_calc(row:BladeRow,upstream:BladeRow,downstream:BladeRow=None,calculat
254
255
  row.T0 = upstream.T0 - T0_coolant_weighted_average(row)
255
256
  row.T = row.T0/T0_T
256
257
  row.V = row.M*np.sqrt(row.gamma*row.R*row.T)
257
- VV = row.V*np.cos(row.phi)
258
- row.Vx = VV*np.cos(row.alpha2)
259
- row.Vt = VV*np.sin(row.alpha2)
258
+ row.Vx = row.Vm*np.cos(row.phi)
260
259
  row.Vr = row.V*np.sin(row.phi)
261
260
  row.Vm = np.sqrt(row.Vx**2+row.Vr**2)
262
- else: # We know Vm, P0, T0
261
+ row.Vt = row.Vm*np.tan(row.alpha2)
262
+ else: # We know Vm, P0, T0, P
263
263
  row.Vx = row.Vm*np.cos(row.phi)
264
264
  row.Vr = row.Vm*np.sin(row.phi)
265
- row.Vt = row.Vm*np.cos(row.phi)*np.tan(row.alpha2)
265
+ row.Vt = row.Vm*np.tan(row.alpha2)
266
266
  row.V = np.sqrt(row.Vx**2 + row.Vr**2 + row.Vt**2)
267
- for _ in range(3): # Mach is a function of T and T is a function of Mach
268
- row.M = row.V/np.sqrt(row.gamma*row.R*row.T)
269
- T0_T = (1+(row.gamma-1)/2 * row.M**2)
270
- row.P = row.P0 *(1/T0_T)**(row.gamma/(row.gamma-1))
271
- row.T = row.T0 * (1/T0_T)
267
+
268
+ row.T = row.P/(row.R*row.rho) # We know P, this is a guess
269
+ row.M = row.V/np.sqrt(row.gamma*row.R*row.T)
272
270
 
273
271
  if upstream.row_type == RowType.Rotor:
274
272
  row.alpha1 = upstream.alpha2 # Upstream rotor absolute frame flow angle
@@ -296,13 +294,14 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
296
294
  upstream.U = upstream.rpm*np.pi/30 * upstream_radius # rad/s
297
295
  upstream.Wt = upstream.Vt - upstream.U
298
296
  upstream.W = np.sqrt(upstream.Vx**2 + upstream.Wt**2 + upstream.Vr**2)
299
- upstream.beta2 = np.arctan2(upstream.Wt,upstream.Vx)
297
+ upstream.beta2 = np.arctan2(upstream.Wt,upstream.Vm)
300
298
  upstream.T0R = upstream.T+upstream.W**2/(2*upstream.Cp)
301
299
  upstream.P0R = upstream.P * (upstream.T0R/upstream.T)**((upstream.gamma)/(upstream.gamma-1))
302
300
  upstream.M_rel = upstream.W/np.sqrt(upstream.gamma*upstream.R*upstream.T)
303
301
 
304
302
  upstream_rothalpy = upstream.T0R*upstream.Cp - 0.5*upstream.U**2 # H01R - 1/2 U1^2
305
-
303
+ if np.any(upstream_rothalpy < 0):
304
+ print('U is too high, reduce RPM or radius')
306
305
  # Rotor Exit Calculations
307
306
  row.beta1 = upstream.beta2
308
307
  #row.Yp # Evaluated earlier
@@ -319,26 +318,26 @@ def rotor_calc(row:BladeRow,upstream:BladeRow,calculate_vm:bool=True):
319
318
  # Need to adjust T
320
319
  print(f'nan detected: check flow path. Turbine inlet cut should be horizontal')
321
320
  row.Vr = row.W*np.sin(row.phi)
322
- row.Wt = np.sqrt(row.W**2 - row.Vr**2) * np.sin(row.beta2)
321
+ row.Vm = row.W*np.cos(row.beta2)
322
+ row.Wt = row.W*np.sin(row.beta2)
323
+ row.Vx = row.Vm*np.cos(row.phi)
323
324
  row.Vt = row.Wt + row.U
324
- ww = row.W*np.cos(row.phi)
325
- row.Vx = ww*np.cos(row.beta2)
326
325
  row.V = np.sqrt(row.Vr**2+row.Vt**2+row.Vx**2)
327
326
  row.M = row.V/np.sqrt(row.gamma*row.R*row.T)
328
327
  row.Vm = np.sqrt(row.Vx**2+row.Vr**2)
329
328
  row.T0 = row.T + row.V**2/(2*row.Cp)
330
329
  row.P0 = row.P*(row.T0/row.T)**(row.gamma/(row.gamma-1))
331
- row.alpha2 = np.arctan2(row.Vt,row.Vx)
330
+ row.alpha2 = np.arctan2(row.Vt,row.Vm)
332
331
  else: # We know Vm, P0, T0
333
332
  row.Vr = row.Vm*np.sin(row.phi)
334
333
  row.Vx = row.Vm*np.cos(row.phi)
335
334
 
336
335
  row.W = np.sqrt(2*row.Cp*(row.T0R-row.T))
337
- row.Wt = np.sqrt(row.W**2 - row.Vr**2) * np.sin(row.beta2)
336
+ row.Wt = row.W*np.sin(row.beta2)
338
337
  row.U = row.omega * row.r
339
338
  row.Vt = row.Wt+row.U
340
339
 
341
- row.alpha2 = np.arctan2(row.Vt,row.Vx)
340
+ row.alpha2 = np.arctan2(row.Vt,row.Vm)
342
341
  row.V = np.sqrt(row.Vx**2 + row.Vr**2 + row.Vt**2)
343
342
 
344
343
  row.M = row.V/np.sqrt(row.gamma*row.R*row.T)
@@ -365,7 +364,7 @@ def inlet_calc(row:BladeRow):
365
364
  row.P = row.P0
366
365
  row.rho = row.P/(row.T*row.R)
367
366
  total_area = 0
368
- for _ in range(5): # Lets converge the Mach and Total and Static pressures
367
+ for iter in range(5): # Lets converge the Mach and Total and Static pressures
369
368
  for j in range(1,len(row.percent_hub_shroud)):
370
369
  rho = row.rho[j]
371
370
  tube_massflow = row.massflow[j]-row.massflow[j-1]
@@ -379,6 +378,11 @@ def inlet_calc(row:BladeRow):
379
378
  area[j] = 2*np.pi*C*(S/2*dx**2+row.r[j-1]*dx)
380
379
  total_area += area[j]
381
380
  row.Vm[j] = tube_massflow/(rho*area[j])
381
+ avg_mach = np.mean(row.M)
382
+ if np.mean(row.M)>0.5:
383
+ print(f"High inlet mach can lead to errors iter:{iter} Mach:{avg_mach}")
384
+ if np.mean(row.M)<0.01:
385
+ print(f"Unusually slow flow:{iter} Mach:{avg_mach}")
382
386
  row.Vm[0] = 1/(len(row.Vm)-1)*row.Vm[1:].sum() # Initialize the value at the hub to not upset the mean
383
387
  row.Vr = row.Vm*np.sin(row.phi)
384
388
  row.Vt = row.Vm*np.cos(row.phi)*np.tan(row.alpha2)
@@ -206,7 +206,9 @@ class TurbineSpool(Spool):
206
206
  sign*=-1
207
207
  if len(stage_ids) % 2 == 1:
208
208
  massflow_stage.append(massflow_stage[-1]*sign)
209
-
209
+ deviation = np.std(total_massflow)*2
210
+ if deviation>1.0:
211
+ print("high massflow deviation detected")
210
212
  return np.std(total_massflow)*2 # + abs(sum(massflow_stage)) # Equation 28
211
213
 
212
214
  # Balance the massflow between Stages
@@ -229,27 +231,27 @@ class TurbineSpool(Spool):
229
231
  Returns:
230
232
  _type_: _description_
231
233
  """
232
- try:
233
- if balance_mean_pressure:
234
- for j in range(self.num_streamlines):
235
- Ps_range = outlet_pressure(x0,P0[j],P[j])
236
- for i in range(1,len(blade_rows)-1):
237
- blade_rows[i].P[j] = Ps_range[i-1]
238
- blade_rows[-1].P = P
239
- else:
234
+ # try:
235
+ if balance_mean_pressure:
236
+ for j in range(self.num_streamlines):
237
+ Ps_range = outlet_pressure(x0,P0[j],P[j])
240
238
  for i in range(1,len(blade_rows)-1):
241
- for j in range(self.num_streamlines):
242
- blade_rows[i].P[j] = P[j]*x0[(i-1)*self.num_streamlines+j] # x0 size = num_streamlines -1
243
-
244
- calculate_massflows(blade_rows,True)
245
- print(x0)
246
- return calculate_error(blade_rows)
247
- except:
239
+ blade_rows[i].P[j] = Ps_range[i-1]
240
+ blade_rows[-1].P = P
241
+ else:
248
242
  for i in range(1,len(blade_rows)-1):
249
243
  for j in range(self.num_streamlines):
250
- blade_rows[i].P[j] = P[j]
251
- calculate_massflows(blade_rows,True)
252
- return 10
244
+ blade_rows[i].P[j] = P[j]*x0[(i-1)*self.num_streamlines+j] # x0 size = num_streamlines -1
245
+
246
+ calculate_massflows(blade_rows,True)
247
+ print(x0)
248
+ return calculate_error(blade_rows)
249
+ # except:
250
+ # for i in range(1,len(blade_rows)-1):
251
+ # for j in range(self.num_streamlines):
252
+ # blade_rows[i].P[j] = P[j]
253
+ # calculate_massflows(blade_rows,True)
254
+ # return 10
253
255
  # Break apart the rows to stages
254
256
  outlet_P=list(); outlet_P_guess = list() # Outlet P is the bounds, outlet_p_guess is the guessed values
255
257
 
@@ -534,11 +536,11 @@ def outlet_pressure(percents:List[float],inletP0:float,outletP:float) -> npt.NDA
534
536
  maxP = inletP0
535
537
  minP = outletP
536
538
  if isinstance(percents, float):
537
- Ps = [percents*(minP-maxP)+maxP]
539
+ Ps = [percents*(maxP-minP)+minP]
538
540
  else:
539
541
  Ps = np.zeros(shape=(len(percents),1)); i = 0
540
542
  for p in percents:
541
- Ps[i] = p*(minP-maxP)+maxP
543
+ Ps[i] = p*(maxP - minP) + minP
542
544
  maxP = Ps[i]
543
545
  i+=1
544
546
  return Ps