/
tail_boom.py
200 lines (156 loc) · 5.25 KB
/
tail_boom.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
" tail boom model "
from numpy import pi
from gpkit import Model, parse_variables, Variable, VectorVariable, units
from .tube_spar import TubeSpar
from gpkitmodels.GP.beam.beam import Beam
from gpkitmodels import g
#pylint: disable=exec-used, undefined-variable, invalid-name
#pylint: disable=attribute-defined-outside-init
class TailBoomAero(Model):
""" Tail Boom Aero Model
Variables
---------
Cf [-] tail boom skin friction coefficient
Re [-] tail boom reynolds number
Upper Unbounded
---------------
Re, Cf, l, V, rho (if not rhovalue)
Lower Unbounded
---------------
l, V, rho (if not rhovalue)
LaTex Strings
-------------
Cf C_f
"""
def setup(self, static, state):
self.state = state
exec parse_variables(TailBoomAero.__doc__)
l = self.l = static.l
rho = self.rho = state.rho
self.rhovalue = rho.key.value
V = self.V = state.V
mu = self.mu = state.mu
return [Re == V*rho*l/mu,
Cf >= 0.455/Re**0.3,
]
class TailBoomState(Model):
""" Tail Boom Loading State
Variables
---------
rhosl 1.225 [kg/m^3] air density at sea level
Vne 40 [m/s] never exceed vehicle speed
LaTex Strings
-------------
rhosl \\rho_{\\mathrm{sl}}
Vne V_{\\mathrm{NE}}
"""
def setup(self):
exec parse_variables(TailBoomState.__doc__)
class VerticalBoomTorsion(Model):
""" Tail Boom Torsion from Vertical Tail
Variables
---------
T [N*m] vertical tail moment
taucfrp 210 [MPa] torsional stress limit of carbon
Upper Unbounded
---------------
J
Lower Unbounded
---------------
d0, b, S
LaTex Strings
-------------
taucfrp \\tau_{\\mathrm{CFRP}}
"""
def setup(self, tailboom, vtail, state):
exec parse_variables(VerticalBoomTorsion.__doc__)
J = self.J = tailboom.J
d0 = self.d0 = tailboom.d
b = self.b = vtail.planform.b
S = self.S = vtail.planform.S
rhosl = self.rhosl = state.rhosl
Vne = self.Vne = state.Vne
CLmax = vtail.planform.CLmax
return [T >= 0.5*rhosl*Vne**2*S*CLmax*b,
taucfrp >= T*d0/2/J
]
class TailBoomBending(Model):
""" Tail Boom Bending
Variables
---------
F [N] tail force
th [-] tail boom deflection angle
kappa 0.1 [-] max tail boom deflection
Nsafety 1.0 [-] safety load factor
Variables of length N-1
-----------------------
Mr [N*m] section root moment
Upper Unbounded
---------------
tailboom.I0, tailboom.Sy
tailboom.J (if tailboomJ), tailboom.I (if tailboomJ)
Lower Unbounded
---------------
htail.planform.S, htail.planform.CLmax
tailboom.l, tailboom.deta
state.qne
LaTex Strings
-------------
th \\theta
thmax \\theta_{\\mathrm{max}}
"""
def setup(self, tailboom, htail, state):
N = self.N = tailboom.N
self.state = state
self.htail = htail
self.tailboom = tailboom
exec parse_variables(TailBoomBending.__doc__)
Beam.qbarFun = [1e-10]*N
Beam.SbarFun = [1.]*N
beam = self.beam = Beam(N)
I = tailboom.I
tailboom.I0 = I[0]
l = tailboom.l
S = htail.planform.S
E = tailboom.material.E
Sy = tailboom.Sy
qne = state.qne
CLmax = htail.planform.CLmax
deta = tailboom.deta
sigma = tailboom.material.sigma
constraints = [beam.dx == deta,
F >= qne*S,
beam["\\bar{EI}"] <= E*I/F/l**2/2,
Mr >= beam["\\bar{M}"][:-1]*F*l,
sigma >= Mr/Sy,
th == beam["\\theta"][-1],
beam["\\bar{\\delta}"][-1]*CLmax*Nsafety <= kappa]
self.tailboomJ = hasattr(tailboom, "J")
if self.tailboomJ:
constraints.append(tailboom.J >= 1e-10*units("m^4"))
return constraints, beam
class TailBoom(TubeSpar):
""" Tail Boom Model
Variables
---------
l [ft] tail boom length
S [ft^2] tail boom surface area
b [ft] twice tail boom length
deta 1./(N-1) [-] normalized segment length
tau 1.0 [-] thickness to width ratio
rhoA 0.15 [kg/m^2] total aerial density
Variables of length N-1
-----------------------
cave [in] average segment width
"""
flight_model = TailBoomAero
tailLoad = TailBoomBending
secondaryWeight = None
def setup(self, N=5):
self.N = N
exec parse_variables(TailBoom.__doc__)
self.spar = super(TailBoom, self).setup(N, self)
if self.secondaryWeight:
self.weight.right += rhoA*g*S
d0 = self.d0 = self.d[0]
return self.spar, [S == l*pi*d0, b == 2*l]