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.
- {turbo_design-1.3.8.dist-info → turbo_design-1.3.10.dist-info}/METADATA +2 -1
- turbo_design-1.3.10.dist-info/RECORD +46 -0
- {turbo_design-1.3.8.dist-info → turbo_design-1.3.10.dist-info}/WHEEL +1 -1
- turbodesign/__init__.py +57 -4
- turbodesign/agf.py +346 -0
- turbodesign/arrayfuncs.py +31 -1
- turbodesign/bladerow.py +238 -155
- turbodesign/compressor_math.py +386 -0
- turbodesign/compressor_spool.py +941 -0
- turbodesign/coolant.py +18 -6
- turbodesign/deviation/__init__.py +5 -0
- turbodesign/deviation/axial_compressor.py +3 -0
- turbodesign/deviation/carter_deviation.py +79 -0
- turbodesign/deviation/deviation_base.py +20 -0
- turbodesign/deviation/fixed_deviation.py +42 -0
- turbodesign/enums.py +5 -6
- turbodesign/flow_math.py +158 -0
- turbodesign/inlet.py +126 -56
- turbodesign/isentropic.py +59 -15
- turbodesign/loss/__init__.py +3 -1
- turbodesign/loss/compressor/OTAC_README.md +39 -0
- turbodesign/loss/compressor/__init__.py +54 -0
- turbodesign/loss/compressor/diffusion.py +61 -0
- turbodesign/loss/compressor/lieblein.py +1 -0
- turbodesign/loss/compressor/otac.py +799 -0
- turbodesign/loss/compressor/references/schobeiri-2012-shock-loss-model-for-transonic-and-supersonic-axial-compressors-with-curved-blades.pdf +0 -0
- turbodesign/loss/fixedpolytropic.py +27 -0
- turbodesign/loss/fixedpressureloss.py +30 -0
- turbodesign/loss/losstype.py +2 -30
- turbodesign/loss/turbine/TD2.py +25 -29
- turbodesign/loss/turbine/__init__.py +0 -1
- turbodesign/loss/turbine/ainleymathieson.py +6 -5
- turbodesign/loss/turbine/craigcox.py +6 -5
- turbodesign/loss/turbine/fixedefficiency.py +8 -7
- turbodesign/loss/turbine/kackerokapuu.py +7 -5
- turbodesign/loss/turbine/traupel.py +17 -16
- turbodesign/outlet.py +81 -22
- turbodesign/passage.py +98 -63
- turbodesign/row_factory.py +129 -0
- turbodesign/solve_radeq.py +9 -10
- turbodesign/{td_math.py → turbine_math.py} +144 -185
- turbodesign/turbine_spool.py +1219 -0
- turbo_design-1.3.8.dist-info/RECORD +0 -33
- turbodesign/compressorspool.py +0 -60
- turbodesign/loss/turbine/fixedpressureloss.py +0 -25
- turbodesign/rotor.py +0 -38
- turbodesign/spool.py +0 -317
- 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,,
|
turbodesign/compressorspool.py
DELETED
|
@@ -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)
|