turbo-design 1.3.8__py3-none-any.whl → 1.3.10__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.
Files changed (48) hide show
  1. {turbo_design-1.3.8.dist-info → turbo_design-1.3.10.dist-info}/METADATA +2 -1
  2. turbo_design-1.3.10.dist-info/RECORD +46 -0
  3. {turbo_design-1.3.8.dist-info → turbo_design-1.3.10.dist-info}/WHEEL +1 -1
  4. turbodesign/__init__.py +57 -4
  5. turbodesign/agf.py +346 -0
  6. turbodesign/arrayfuncs.py +31 -1
  7. turbodesign/bladerow.py +238 -155
  8. turbodesign/compressor_math.py +386 -0
  9. turbodesign/compressor_spool.py +941 -0
  10. turbodesign/coolant.py +18 -6
  11. turbodesign/deviation/__init__.py +5 -0
  12. turbodesign/deviation/axial_compressor.py +3 -0
  13. turbodesign/deviation/carter_deviation.py +79 -0
  14. turbodesign/deviation/deviation_base.py +20 -0
  15. turbodesign/deviation/fixed_deviation.py +42 -0
  16. turbodesign/enums.py +5 -6
  17. turbodesign/flow_math.py +158 -0
  18. turbodesign/inlet.py +126 -56
  19. turbodesign/isentropic.py +59 -15
  20. turbodesign/loss/__init__.py +3 -1
  21. turbodesign/loss/compressor/OTAC_README.md +39 -0
  22. turbodesign/loss/compressor/__init__.py +54 -0
  23. turbodesign/loss/compressor/diffusion.py +61 -0
  24. turbodesign/loss/compressor/lieblein.py +1 -0
  25. turbodesign/loss/compressor/otac.py +799 -0
  26. turbodesign/loss/compressor/references/schobeiri-2012-shock-loss-model-for-transonic-and-supersonic-axial-compressors-with-curved-blades.pdf +0 -0
  27. turbodesign/loss/fixedpolytropic.py +27 -0
  28. turbodesign/loss/fixedpressureloss.py +30 -0
  29. turbodesign/loss/losstype.py +2 -30
  30. turbodesign/loss/turbine/TD2.py +25 -29
  31. turbodesign/loss/turbine/__init__.py +0 -1
  32. turbodesign/loss/turbine/ainleymathieson.py +6 -5
  33. turbodesign/loss/turbine/craigcox.py +6 -5
  34. turbodesign/loss/turbine/fixedefficiency.py +8 -7
  35. turbodesign/loss/turbine/kackerokapuu.py +7 -5
  36. turbodesign/loss/turbine/traupel.py +17 -16
  37. turbodesign/outlet.py +81 -22
  38. turbodesign/passage.py +98 -63
  39. turbodesign/row_factory.py +129 -0
  40. turbodesign/solve_radeq.py +9 -10
  41. turbodesign/{td_math.py → turbine_math.py} +144 -185
  42. turbodesign/turbine_spool.py +1219 -0
  43. turbo_design-1.3.8.dist-info/RECORD +0 -33
  44. turbodesign/compressorspool.py +0 -60
  45. turbodesign/loss/turbine/fixedpressureloss.py +0 -25
  46. turbodesign/rotor.py +0 -38
  47. turbodesign/spool.py +0 -317
  48. turbodesign/turbinespool.py +0 -543
@@ -1,33 +0,0 @@
1
- turbodesign/__init__.py,sha256=N8Nu0I1vrlEHYJZZ7yhhg-FtbNbLyrgjy7hoicygUqg,325
2
- turbodesign/arrayfuncs.py,sha256=GHIlTyLfeNsNCQQoh5m1aXK3iyvU6RjdYQipkqpU_ps,519
3
- turbodesign/bladerow.py,sha256=Uad3UUnaRqCaEQBV1mHD04eU_lkz-BWr4n1vjFsX-eA,25472
4
- turbodesign/cantera_gas/co2.yaml,sha256=M2o_RzxV9B9rDkgkXJC-l3voKraFZguTZuKKt4F7S_c,887
5
- turbodesign/compressorspool.py,sha256=z8ZVczJ-EdZvIqqZArC6UdwC5MbU2SZh_MT2CGq5avY,2600
6
- turbodesign/coolant.py,sha256=evDtUFOYhfZKTVAsDWzxRzUX20gTvfjj0uybaWg4CsI,427
7
- turbodesign/enums.py,sha256=WC6VPmHw3UF1zR1SLjj8z00gIWSNso66MShFGoYRY4U,1164
8
- turbodesign/inlet.py,sha256=5uja906IA-_gca4FJykZvFLJ1he6HRy5pZDNQE1D2_g,7945
9
- turbodesign/isentropic.py,sha256=YLTmNx69e_M5fTuLOmk_KvaQ6ABv0aZsityfBihJOmI,2003
10
- turbodesign/loss/__init__.py,sha256=jltNIIbUntGKq2IfX3EKUNEajIcHdOB7pWuj5tLtmGw,66
11
- turbodesign/loss/compressor/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
12
- turbodesign/loss/losstype.py,sha256=ViUf1ue3DZ3qFAhLUP3ps2fyygNH6udekAr53vEzrY8,1776
13
- turbodesign/loss/turbine/TD2.py,sha256=evyTG4K6s56NGdjxrZFD3G7zsB8_2lJTBOxT3Ju2uG8,5207
14
- turbodesign/loss/turbine/__init__.py,sha256=d1UrbiIicO60FhDlOemo_irYW2asUaYoqlXUz-UG9zk,285
15
- turbodesign/loss/turbine/ainleymathieson.py,sha256=uTl1wXcJZmNjeerGTYDYCs0vJhyMPjG_0C9xlvSKYqY,5911
16
- turbodesign/loss/turbine/craigcox.py,sha256=2dydHVvxTKhmJsRHO7Vf2JFKM6xaUSeT_CPxf8PCtWs,9942
17
- turbodesign/loss/turbine/fixedefficiency.py,sha256=JJv4GUS5q9pvuf3akjBtlcHOykRYmRVFfDDrdWqH6S4,774
18
- turbodesign/loss/turbine/fixedpressureloss.py,sha256=sgkm6uQwz6Qz2LDCEmir46aJRSPLAdCKpDyR1hNdgQ8,682
19
- turbodesign/loss/turbine/kackerokapuu.py,sha256=TQkTKG6ZdpsdEp1-qJfacQR8EEZSQ1qjUmOTf3t7mws,7263
20
- turbodesign/loss/turbine/traupel.py,sha256=8KDjalPgBW3GoZUL7jgsyPFoDwNfcQhzmeRNrsZA0XA,4369
21
- turbodesign/lossinterp.py,sha256=B2KEobp-nD9jwD6UINgBmTlH9kKyWg3UNvXxqfUsr-k,6198
22
- turbodesign/outlet.py,sha256=MaZJ-mDuLvh19AashnMQLx2XlR-Rk1r0HQS4kE0OxeI,2191
23
- turbodesign/passage.py,sha256=RZ8giKMcpJI7EnO4SEnbGYcPFmKdGyzWC0UZTXHnS6g,12181
24
- turbodesign/radeq.py,sha256=LEqYxZZocCZyVPhY09MNFTnAkEXM740-SR6QxXW8Ssg,6522
25
- turbodesign/rotor.py,sha256=tHl9o5H4aQ6Etd4gqa8Ime1UK7k0de4GLt5Yb1sJdGs,1376
26
- turbodesign/solve_radeq.py,sha256=nLYlRtXElPgHaoUP9jwMulRmYKTJs_uQ1eCulk2V59I,1938
27
- turbodesign/spool.py,sha256=81UFbBi5JKm0RJ_hjB40bKWeCXx0V2lt0b2VAwOtTDU,14376
28
- turbodesign/stage.py,sha256=UP45sDKDLsAkO_WfDWJ6kqXU7cYKh_4QO01QZnSN1oQ,166
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,,
@@ -1,60 +0,0 @@
1
- from typing import List
2
- from cantera import composite
3
- from cantera.composite import Solution
4
- from .bladerow import BladeRow,RowType
5
- from .spool import Spool
6
- import json
7
-
8
- class CompressorSpool(Spool):
9
- def __init__(self,rhub:List[float],xhub:List[float],
10
- rshroud:List[float],xshroud:List[float],
11
- massflow:float,rows=List[BladeRow],
12
- num_streamlines:int=3,
13
- fluid:Solution=Solution('air.yaml'),rpm:float=-1):
14
- """Initializes a Compressor Spool
15
-
16
- Args:
17
- rhub (List[float]): hub radius. Units meters
18
- xhub (List[float]): x location of each hub radius station. Units meters
19
- rshroud (List[float]): shroud radius. Units meters
20
- xshroud (List[float]): x location of each shroud radius. Units meters
21
- massflow (float): massflow at spool inlet
22
- rows (List[BladeRow], optional): List of blade rows. Defaults to List[BladeRow].
23
- num_streamlines (int, optional): number of streamlines. Defaults to 3.
24
- gas (ct.Solution, optional): cantera gas solution. Defaults to ct.Solution('air.yaml').
25
- rpm (float, optional): RPM for the entire spool Optional, you can also set rpm of the blade rows individually. Defaults to -1.
26
- power_target (float, optional): Sets a target power in kW
27
- """
28
- super().__init__(rhub, xhub, rshroud, xshroud, massflow, rows,num_streamlines, fluid, rpm)
29
-
30
- pass
31
-
32
- def export_properties(self,filename:str="compressor_spool.json"):
33
- """Export the spool object to json
34
-
35
- Args:
36
- filename (str, optional): name of export file. Defaults to "spool.json".
37
- """
38
- blade_rows = list()
39
- total_total_efficiency = list()
40
-
41
- for indx,row in enumerate(self.blade_rows):
42
- blade_rows.append(row.to_dict()) # Appending data
43
- if row.row_type == RowType.Stator:
44
- pass
45
-
46
- data = {
47
- "blade_rows": blade_rows,
48
- "massflow":self.massflow,
49
- "rpm":self.rpm,
50
- "r_streamline":self.r_streamline.tolist(),
51
- "x_streamline":self.x_streamline.tolist(),
52
- "rhub":self.rhub.tolist(),
53
- "rshroud":self.rshroud.tolist(),
54
- "xhub":self.xhub.tolist(),
55
- "xshroud":self.xshroud.tolist(),
56
- "num_streamlines":self.num_streamlines,
57
- }
58
- # Dump all the Python objects into a single JSON file.
59
- with open(filename, "w") as f:
60
- json.dump(data, f, indent=4)
@@ -1,25 +0,0 @@
1
- from ...bladerow import BladeRow
2
- from ..losstype import LossBaseClass
3
- from ...enums import LossType
4
-
5
- class FixedPressureLoss(LossBaseClass):
6
- pressure_loss:float
7
-
8
- def __init__(self,pressure_loss:float):
9
- """Fixed Pressure Loss
10
- """
11
- super().__init__(LossType.Pressure)
12
- self.pressure_loss = pressure_loss
13
-
14
-
15
- def __call__(self,row:BladeRow, upstream:BladeRow) -> float:
16
- """Outputs the fixed Pressure Loss
17
-
18
- Args:
19
- upstream (BladeRow): Upstream blade row
20
- row (BladeRow): downstream blade row
21
-
22
- Returns:
23
- float: Pressure Loss
24
- """
25
- return self.pressure_loss
turbodesign/rotor.py DELETED
@@ -1,38 +0,0 @@
1
- from dataclasses import dataclass, field
2
- from .enums import RowType
3
- from .bladerow import BladeRow
4
- from .arrayfuncs import convert_to_ndarray
5
- import numpy as np
6
-
7
- class Rotor(BladeRow):
8
- """Station defined at rotor exit
9
-
10
- Inherits:
11
- (BladeRow): Defines the properties of the blade row
12
- """
13
-
14
- beta2:np.ndarray = field(default_factory=lambda: np.array([72])) # Degrees
15
- M_rel:np.ndarray = field(default_factory=lambda: np.array([1.2])) # Relative mach number
16
- power:float = 0 # Watts
17
-
18
- def __init__(self,power:float=50000):
19
- """Initialize the Rotor
20
-
21
- Args:
22
- coolant_P0 (float, optional): Coolant massflow used to cool the rotor internal cooling, tip leakage, hub disk leakage. Defaults to 0.
23
- coolant_T0 (float, optional): _description_. Defaults to 500.
24
- power (float, optional): _description_. Defaults to 50000.
25
- """
26
- self.row_type = RowType.RotorExit
27
- self.power = power
28
- super().__init__(self)
29
-
30
- def initialize_rotor_exit(self,beta:float,M_exit:float):
31
- """Uses the beta and exit mach number to predict a value for Vm
32
-
33
- Args:
34
- beta (float): exit relative flow angle
35
- M_exit (float): exit relative mach number
36
- """
37
- self.beta2 = convert_to_ndarray(beta)
38
- self.M_rel = convert_to_ndarray(M_exit)
turbodesign/spool.py DELETED
@@ -1,317 +0,0 @@
1
- # type: ignore[arg-type, reportUnknownArgumentType]
2
- from dataclasses import field
3
- import json
4
- from typing import Dict, List, Union, Optional
5
- import matplotlib.pyplot as plt
6
- from .bladerow import BladeRow
7
- import numpy as np
8
- import numpy.typing as npt
9
- from .enums import RowType, MassflowConstraint
10
- from cantera.composite import Solution
11
- from .loss.turbine import TD2
12
- from pyturbo.helper import line2D
13
- from scipy.interpolate import interp1d
14
- from .passage import Passage
15
- from .inlet import Inlet
16
- from .outlet import Outlet
17
-
18
- class Spool:
19
- blade_rows:List[BladeRow]=[]
20
- massflow:float=0
21
- rpm:float = 0
22
-
23
- passage:Passage
24
- t_streamline: npt.NDArray = field(default_factory=lambda: np.zeros((10,)))
25
- num_streamlines:int=0
26
-
27
- # Fluid entering the spool
28
- _fluid: Solution = Solution("air.yaml")
29
-
30
- massflow_constraint: MassflowConstraint
31
- _adjust_streamlines:bool = True
32
-
33
- # Inlet Conditions
34
- def __init__(self,passage:Passage,
35
- massflow:float,rows:List[BladeRow],
36
- num_streamlines:int=3,
37
- fluid:Solution=None,
38
- rpm:float=-1,
39
- massflow_constraint:MassflowConstraint=MassflowConstraint.MatchMassFlow):
40
- """Initializes a Spool
41
-
42
-
43
- Note:
44
- When it comes to massflow, the exit angle of the blade rows along with the upstream total pressure is used to set the massflow through the spool. If turning is too high then massflow is limited and cannot.
45
- This code gives you the option of setting a massflow and varying the exit angles to match that particular massflow. (MatchMassflow)
46
- Or keeping the exit angle and modifying the inlet condition to set a specific massflow through the stage. (BalanceMassflow)
47
-
48
- Args:
49
- passage (Passage): Passage defining hub and shroud
50
- massflow (float): massflow at spool inlet
51
- rows (List[BladeRow], optional): List of blade rows. Defaults to List[BladeRow].
52
- num_streamlines (int, optional): number of streamlines. Defaults to 3.
53
- fluid (ct.Solution, optional): cantera gas solution. Defaults to None, fluid is set by bladerow cp
54
- rpm (float, optional): RPM for the entire spool Optional, you can also set rpm of the blade rows individually. Defaults to -1.
55
- massflow_constraint (MassflowConstraint, optional): MatchMassflow - Matches the massflow defined in the spool. BalanceMassflow - Balances the massflow between BladeRows, matches the lowest massflow.
56
- """
57
- self.passage = passage
58
- self.fluid = fluid
59
- self.massflow = massflow
60
- self.num_streamlines = num_streamlines
61
- self.blade_rows = rows
62
- self.massflow_constraint = massflow_constraint
63
-
64
- self.rpm = rpm
65
-
66
- for i in range(len(self.blade_rows)):
67
- '''Defining RPM in the bladerows
68
- There's 2 ways of setting the RPM.
69
- 1. Conventional: Stator-Rotor-Stator-Rotor-etc. Set the RPM equally across all
70
- 2. Counter Rotation: We either use the RPM already persecribed for each blade row.
71
- '''
72
- self.blade_rows[i].id = i
73
- if (type(self.blade_rows[i]) != Inlet) and (type(self.blade_rows[i]) != Outlet):
74
- self.blade_rows[i].rpm = rpm
75
- self.blade_rows[i].axial_chord = self.blade_rows[i].location * self.passage.hub_length
76
-
77
-
78
- @property
79
- def fluid(self) -> Optional[Solution]:
80
- return self._fluid
81
-
82
- @fluid.setter
83
- def fluid(self,newFluid:Solution):
84
- """Change the type of gas used in the spool
85
-
86
- Args:
87
- new_gas (ct.Solution.Solution): New gas mixture
88
- """
89
- self._fluid = newFluid
90
- for i in range(len(self.blade_rows)):
91
- self.blade_rows[i].fluid = self.fluid
92
-
93
- @property
94
- def adjust_streamlines(self) -> bool:
95
- """Variable that determines whether or not to try and adjust the streamlines to balance massflow
96
- This can be a source of failure. Setting it to false may help with debugging.
97
-
98
- Returns:
99
- bool: True = streamlines are adjusted after calculation; False = No changes in streamlines
100
- """
101
- return self._adjust_streamlines
102
-
103
- @adjust_streamlines.setter
104
- def adjust_streamlines(self,val:bool):
105
- """Variable that determines whether or not to try and adjust the streamlines to balance massflow
106
- This can be a source of failure. Setting it to false may help with debugging.
107
- """
108
- self._adjust_streamlines = val
109
-
110
-
111
- def set_blade_row_rpm(self,index:int,rpm:float):
112
- """sets the rpm of a particular blade row"""
113
- self.blade_rows[index].rpm = rpm
114
-
115
- def set_blade_row_type(self,blade_row_index:int,rowType:RowType):
116
- """Sets a blade row to be a different type.
117
-
118
- Args:
119
- blade_row_index (int): Index of blade row. Keep in mind Blade row 0 is inlet, -1 = outlet
120
- """
121
- self.blade_rows[blade_row_index].row_type = rowType
122
-
123
- def set_blade_row_exit_angles(self,radius:Dict[int,List[float]],beta:Dict[int,List[float]],IsSupersonic:bool=False):
124
- """Set the intended exit flow angles for the spool.
125
-
126
- Useful if you already have a geometry that you want to simulate
127
-
128
- You can set the values for each blade row or simply the inlet and exit
129
-
130
- Args:
131
- radius (np.ndarray): Matrix containing [[r1,r2,r3],[r1,r2,r3]] blade_rows x radial locations
132
- beta (Dict[int,List[float]]): Metal Angle of the geometry, it is assumed that the fluid will leave at this angle.
133
- IsSupersonic(bool): if solution is supersonic at spool exit
134
-
135
- Example:
136
- # Station 0 has angles of [73.1,74.2,75.4]
137
- # Station 5 has angles of [69,69,69]
138
- beta = {0: [73.1,74.2,75.4], 5: [69,69,69]}
139
-
140
- """
141
- for k,v in radius.items():
142
- self.blade_rows[k].radii_geom = v
143
- for k,v in beta.items():
144
- self.blade_rows[k].beta_geom = v
145
- self.blade_rows[k].beta_fixed = True
146
- for br in self.blade_rows:
147
- if not IsSupersonic:
148
- br.solution_type = SolutionType.subsonic
149
- else:
150
- br.solution_type = SolutionType.supersonic
151
-
152
-
153
- def initialize_streamlines(self):
154
- """Initialize streamline and compute the curvature.
155
- This function is called once
156
- """
157
-
158
- for row in self.blade_rows:
159
- row.phi = np.zeros((self.num_streamlines,))
160
- row.rm = np.zeros((self.num_streamlines,))
161
- row.r = np.zeros((self.num_streamlines,))
162
- row.m = np.zeros((self.num_streamlines,))
163
-
164
- t_radial = np.linspace(0,1,self.num_streamlines)
165
- self.calculate_streamline_curvature(row,t_radial)
166
-
167
- # Set the loss function if it's not set
168
- if (type(row)!= Inlet and type(row) != Outlet):
169
- if row.loss_function == None:
170
- row.loss_function = TD2()
171
-
172
- def calculate_streamline_curvature(self,row:BladeRow,t_radial:Union[List[float],npt.NDArray]):
173
- """Called to calculate new streamline curvature
174
-
175
- Args:
176
- row (BladeRow): blade row
177
- t_radial (Union[List[float],npt.NDArray]): normalized streamline radial locations
178
- """
179
- for i,tr in enumerate(t_radial):
180
- t_streamline, x_streamline, r_streamline = self.passage.get_streamline(tr)
181
- phi, rm, r = self.passage.streamline_curvature(x_streamline,r_streamline)
182
- row.phi[i] = float(interp1d(t_streamline,phi)(row.location))
183
- row.rm[i] = float(interp1d(t_streamline,rm)(row.location))
184
- row.r[i] = float(interp1d(t_streamline,r)(row.location))
185
- row.m[i] = float(interp1d(t_streamline,self.passage.get_m(tr,resolution=len(t_streamline)))(row.location))
186
-
187
- def solve(self):
188
- raise NotImplementedError('Solve is not implemented')
189
-
190
-
191
- def plot(self):
192
- """Plots the hub, shroud, and all the streamlines
193
- """
194
- plt.figure(num=1,clear=True,dpi=150,figsize=(15,10))
195
- plt.plot(self.passage.xhub_pts,self.passage.rhub_pts,label='hub',linestyle='solid',linewidth=2,color='black')
196
- plt.plot(self.passage.xshroud_pts,self.passage.rshroud_pts,label='shroud',linestyle='solid',linewidth=2,color='black')
197
-
198
- hub_length = np.sum(np.sqrt(np.diff(self.passage.xhub_pts)**2 + np.diff(self.passage.rhub_pts)**2))
199
- # Populate the streamlines
200
- x_streamline = np.zeros((self.num_streamlines,len(self.blade_rows)))
201
- r_streamline = np.zeros((self.num_streamlines,len(self.blade_rows)))
202
- for i in range(len(self.blade_rows)):
203
- x_streamline[:,i] = self.blade_rows[i].x
204
- r_streamline[:,i] = self.blade_rows[i].r
205
-
206
- for i in range(1,len(self.blade_rows)-1): # plot dashed lines for each steamline
207
- plt.plot(x_streamline[:,i],r_streamline[:,i],'--b',linewidth=1.5)
208
-
209
- for i in range(len(self.blade_rows)):
210
-
211
- row = self.blade_rows[i]
212
- plt.plot(row.x,row.r,linestyle='dashed',linewidth=1.5,color='blue',alpha=0.4)
213
- plt.plot(x_streamline[:,i],r_streamline[:,i],'or')
214
-
215
- if i == 0:
216
- pass # Inlet
217
- else: # i>0
218
- upstream = self.blade_rows[i-1]
219
- if upstream.row_type== RowType.Inlet:
220
- cut_line1,_,_ = self.passage.get_cutting_line((row.location*hub_length +(0.5*row.blade_to_blade_gap*row.axial_chord) - row.axial_chord)/hub_length)
221
- else:
222
- cut_line1,_,_ = self.passage.get_cutting_line((upstream.location*hub_length)/hub_length)
223
- cut_line2,_,_ = self.passage.get_cutting_line((row.location*hub_length-(0.5*row.blade_to_blade_gap*row.axial_chord))/hub_length)
224
-
225
- if self.blade_rows[i].row_type == RowType.Stator:
226
- x1,r1 = cut_line1.get_point(np.linspace(0,1,10))
227
- plt.plot(x1,r1,'m')
228
- x2,r2 = cut_line2.get_point(np.linspace(0,1,10))
229
- plt.plot(x2,r2,'m')
230
- x_text = (x1+x2)/2; r_text = (r1+r2)/2
231
- plt.text(x_text.mean(),r_text.mean(),"Stator",fontdict={"fontsize":"xx-large"})
232
- elif self.blade_rows[i].row_type == RowType.Rotor:
233
- x1,r1 = cut_line1.get_point(np.linspace(0,1,10))
234
- plt.plot(x1,r1,color='brown')
235
- x2,r2 = cut_line2.get_point(np.linspace(0,1,10))
236
- plt.plot(x2,r2,color='brown')
237
- x_text = (x1+x2)/2; r_text = (r1+r2)/2
238
- plt.text(x_text.mean(),r_text.mean(),"Rotor",fontdict={"fontsize":"xx-large"})
239
- plt.axis('scaled')
240
- plt.savefig(f"Meridional.png",transparent=False,dpi=150)
241
- plt.show()
242
-
243
- def plot_velocity_triangles(self):
244
- """Plots the velocity triangles for each blade row
245
- Made for turbines
246
- """
247
- prop = dict(arrowstyle="-|>,head_width=0.4,head_length=0.8",
248
- shrinkA=0,shrinkB=0)
249
-
250
-
251
- for j in range(self.num_streamlines):
252
- x_start = 0
253
- y_max = 0; y_min = 0
254
- plt.figure(num=1,clear=True)
255
- for i in range(1,len(self.blade_rows)-1): # Don't plot inlet or outlet
256
- row = self.blade_rows[i]
257
- x_end = x_start + row.Vm.mean()
258
- dx = x_end - x_start
259
-
260
- Vt = row.Vt[j]
261
- Wt = row.Wt[j]
262
- U = row.U[j]
263
-
264
- y_max = (Vt if Vt>y_max else y_max)
265
- y_max = (Wt if Wt>y_max else y_max)
266
-
267
- y_min = (Vt if Vt<y_min else y_min)
268
- y_min = (Wt if Wt<y_min else y_min)
269
-
270
- # V
271
- plt.annotate("", xy=(x_end,Vt), xytext=(x_start,0), arrowprops=prop)
272
- plt.text((x_start+x_end)/2,Vt/2*1.1,"V",fontdict={"fontsize":"xx-large"})
273
-
274
- # W
275
- plt.annotate("", xy=(x_end,Wt), xytext=(x_start,0), arrowprops=prop)
276
- plt.text((x_start+x_end)/2,Wt/2*1.1,"W",fontdict={"fontsize":"xx-large"})
277
-
278
- if (abs(row.Vt[j]) > abs(row.Wt[j])):
279
- # Shift Vt to right just a bit so we can see it
280
- plt.annotate("", xy=(x_end,Wt), xytext=(x_end,0), arrowprops=prop) # Wt
281
- plt.text(x_end+dx*0.1,Wt/2,"Wt",fontdict={"fontsize":"xx-large"})
282
-
283
- plt.annotate("", xy=(x_end,U+Wt), xytext=(x_end,Wt), arrowprops=prop) # U
284
- plt.text(x_end+dx*0.1,(Wt+U)/2,"U",fontdict={"fontsize":"xx-large"})
285
- else:
286
- # Shift Wt to right just a bit so we can see it
287
- plt.annotate("", xy=(x_end,Vt), xytext=(x_end,0), arrowprops=prop) # Vt
288
- plt.text(x_end+dx*0.1,Vt/2,"Vt",fontdict={"fontsize":"xx-large"})
289
-
290
- plt.annotate("", xy=(x_end,Wt+U), xytext=(x_end,Wt), arrowprops=prop) # U
291
- plt.text(x_end+dx*0.1,Wt+U/2,"U",fontdict={"fontsize":"xx-large"})
292
-
293
- if -np.sign(Vt)>0:
294
- y = y_min
295
- else:
296
- y = y_max
297
- plt.text((x_start+x_end)/2,-np.sign(Vt)*y*0.95,row.row_type.name,fontdict={"fontsize":"xx-large"})
298
- x_start += row.Vm[j]
299
- plt.axis([0,x_end+dx, y_min, y_max])
300
- plt.ylabel("Tangental Velocity [m/s]")
301
- plt.xlabel("Vm [m/s]")
302
- plt.title(f"Velocity Triangles for Streamline {j}")
303
- plt.savefig(f"streamline_{j:04d}.png",transparent=False,dpi=150)
304
-
305
-
306
-
307
-
308
-
309
- def JSON_to_Spool(filename:str="spool.json"):
310
- """Reads a JSON file with the properties
311
- #! Need to instantiate and return spool. Fluid isn't loaded fyi
312
-
313
- Args:
314
- filename (str, optional): json filename with properties . Defaults to "spool.json".
315
- """
316
- with open(filename, "r") as f:
317
- data = json.load(f)