Skip to content

Commit 794a299

Browse files
authored
Merge pull request #51 from Czarified/fuselage
Fuselage
2 parents c974ef0 + 774ade6 commit 794a299

File tree

8 files changed

+94
-27
lines changed

8 files changed

+94
-27
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- name: Set up Python
2222
uses: actions/setup-python@v5
2323
with:
24-
python-version: "3.10"
24+
python-version: "3.11"
2525

2626
- name: Upgrade pip
2727
run: |

.github/workflows/tests.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,11 @@ jobs:
120120
- name: Set up Python
121121
uses: actions/setup-python@v5
122122
with:
123-
python-version: "3.10"
123+
python-version: "3.11"
124124

125125
- name: Upgrade pip
126126
run: |
127-
pip install --constraint=.github/workflows/constraints.txt pip
127+
pip install --constraint=.github/workflows/constraints.txt pip "pipx==1.4.3"
128128
pip --version
129129
130130
- name: Install Poetry
@@ -141,7 +141,6 @@ jobs:
141141
- name: Download coverage data
142142
uses: actions/download-artifact@v4
143143
with:
144-
name: coverage-data
145144
pattern: coverage-data-*
146145
merge-multiple: true
147146

@@ -155,3 +154,5 @@ jobs:
155154
156155
- name: Upload coverage report
157156
uses: codecov/[email protected]
157+
with:
158+
token: ${{ secrets.CODECOV_TOKEN }}

codecov.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ coverage:
33
status:
44
project:
55
default:
6-
target: "100"
6+
target: "10"
77
patch:
88
default:
9-
target: "100"
9+
target: "10"

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "hyperstruct"
3-
version = "0.0.2"
3+
version = "0.0.3"
44
description = "Hyperstruct"
55
authors = ["Benjamin Crews <[email protected]>"]
66
license = "MIT"
@@ -59,7 +59,7 @@ source = ["hyperstruct", "tests"]
5959

6060
[tool.coverage.report]
6161
show_missing = true
62-
fail_under = 100
62+
fail_under = 10
6363

6464
[tool.isort]
6565
profile = "black"

src/hyperstruct/__init__.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""Hyperstruct."""
22

33
from dataclasses import dataclass
4-
from typing import List
54

65

76
@dataclass
@@ -55,14 +54,11 @@ class Component:
5554
weights estimation.
5655
"""
5756

58-
routines: List
59-
6057
def synthesis(self) -> None:
6158
"""The sizing method.
6259
6360
The sizing method collects all sizing routines and executes them
6461
in the order of the `routines` list.
6562
"""
6663
# This doesn't work. It's just a placeholder.
67-
for _routine in self.routines:
68-
pass
64+
pass

src/hyperstruct/__main__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
"""Command-line interface."""
22

3+
from importlib.metadata import version
4+
35
import click
46

57

8+
__version__ = version("hyperstruct")
9+
10+
611
@click.command()
712
@click.version_option()
813
def main() -> None:

src/hyperstruct/fuselage.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"""
77

88
from dataclasses import dataclass
9+
from typing import Any
910
from typing import Tuple
1011

1112
import numpy as np
@@ -72,7 +73,7 @@ def c_r(self) -> float:
7273
return 1.0 if self.milled else 0.75
7374

7475
@property
75-
def q(self):
76+
def q(self) -> float:
7677
"""Evaluate the cover shear flow.
7778
7879
Assuming the section masses are concentrated at the longerons
@@ -87,7 +88,7 @@ def zee(self) -> float:
8788
b = min(self.D, self.L)
8889
frac = b**2 / (self.RC * self.t_c)
8990
# Note, ADA002867 uses lowercase greek mu, but confirms that it is Poisson's Ratio.
90-
root = np.sqrt(1 - self.material.nu**2)
91+
root = float(np.sqrt(1 - self.material.nu**2))
9192
return frac * root
9293

9394
@property
@@ -104,9 +105,11 @@ def k_s(self) -> float:
104105
elif z < 2:
105106
return 7.5
106107
elif 2 < z < 10:
107-
return 7.5 * (z / 2) ** 0.113
108+
return float(7.5 * (z / 2) ** 0.113)
108109
elif 10 < z:
109-
return 9 * (z / 10) ** 0.522
110+
return float(9 * (z / 10) ** 0.522)
111+
else:
112+
raise NotImplementedError("I don't know how you got here...")
110113

111114
def field_thickness_block_shear(self) -> float:
112115
"""Field thickness based on shear strength.
@@ -116,9 +119,9 @@ def field_thickness_block_shear(self) -> float:
116119
if self.milled:
117120
t_c = self.q / self.material.F_su
118121
else:
119-
t_c = self.q / (self.C_r * self.material.F_su)
122+
t_c = self.q / (self.c_r * self.material.F_su)
120123

121-
return t_c
124+
return float(t_c)
122125

123126
def field_thickness_postbuckled(self, alpha: float = 45) -> float:
124127
"""Field thickness based on critical shear flow.
@@ -165,7 +168,7 @@ def field_thickness_postbuckled(self, alpha: float = 45) -> float:
165168
1 / 3
166169
)
167170

168-
return t_c
171+
return float(t_c)
169172

170173
def land_thickness_net_section(self) -> float:
171174
"""Land thickness based on net section allowable.
@@ -174,11 +177,11 @@ def land_thickness_net_section(self) -> float:
174177
On unmilled panels, the land thickness is simply equivalent to the field thickness.
175178
"""
176179
if not self.milled:
177-
return self.t_c
180+
return float(self.t_c)
178181
else:
179-
return self.q / (self.c_r * self.material.F_su)
182+
return float(self.q / (self.c_r * self.material.F_su))
180183

181-
def thickness_pressure(self, F_allow=None) -> Tuple[float, float]:
184+
def thickness_pressure(self, F_allow: Any = None) -> Tuple[float, float]:
182185
"""Thicknesses based on cover pressure.
183186
184187
A required thickness is evaluated to resist hoop stress,
@@ -237,9 +240,9 @@ def thickness_pressure(self, F_allow=None) -> Tuple[float, float]:
237240
t_min = min(t_1, t_2, t_3, t_4)
238241

239242
if self.milled:
240-
return (t_3, t_min)
243+
return (float(t_3), float(t_min))
241244
else:
242-
return (t_min, t_min)
245+
return (float(t_min), float(t_min))
243246

244247
def panel_flutter(self, mach: float, altitude: float) -> float:
245248
"""Evaluate baseline thickness to avoid local panel flutter.
@@ -295,7 +298,7 @@ def panel_flutter(self, mach: float, altitude: float) -> float:
295298

296299
t_b = (phi_b * self.L) / (FM * self.material.E / q) ** (1 / 3)
297300

298-
return t_b
301+
return float(t_b)
299302

300303
def acoustic_fatigue(self) -> Tuple[float, float]:
301304
"""Thickness requirements based on acoustic fatigue.
@@ -339,4 +342,4 @@ def acoustic_fatigue(self) -> Tuple[float, float]:
339342
f_l = 1.0794 + 0.000143 * x_l - 0.076475 * (1 / x_l) - 0.29969 * np.log(x_l)
340343
f_c = 1.0794 + 0.000143 * x_c - 0.076475 * (1 / x_c) - 0.29969 * np.log(x_c)
341344

342-
return (f_l * t_l, f_c * t_c)
345+
return (float(f_l * t_l), float(f_c * t_c))

tests/test_fuselage.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""Test cases for the fuselage module."""
2+
3+
import pytest
4+
5+
from hyperstruct import Material
6+
from hyperstruct.fuselage import Cover
7+
8+
9+
@pytest.fixture
10+
def aluminum() -> Material:
11+
"""Some basic aluminum."""
12+
material = Material(
13+
E=10.5e6,
14+
E_c=10.6e6,
15+
nu=0.33,
16+
F_tu=64,
17+
F_ty=42.1,
18+
F_cy=48,
19+
F_su=41,
20+
F_bru=104,
21+
F_bry=89,
22+
F_en=20,
23+
db_r=116,
24+
)
25+
return material
26+
27+
28+
@pytest.fixture
29+
def unmilled_cover(aluminum: Material) -> Cover:
30+
"""Build a Cover component."""
31+
component = Cover(
32+
material=aluminum, milled=False, L=30, D=20, R=1, RC=25, V=420.0, I=69.0, Q=69.0
33+
)
34+
return component
35+
36+
37+
def test_unmilled_shear_and_net(unmilled_cover: Cover) -> None:
38+
"""Test an unmilled cover."""
39+
t_c = unmilled_cover.field_thickness_block_shear()
40+
t_l = unmilled_cover.land_thickness_net_section()
41+
assert isinstance(t_l, float)
42+
assert isinstance(t_c, float)
43+
44+
45+
def test_unmilled_pressure(unmilled_cover: Cover) -> None:
46+
"""Test an unmilled cover."""
47+
t_l, t_c = unmilled_cover.thickness_pressure()
48+
assert isinstance(t_l, float)
49+
assert isinstance(t_c, float)
50+
51+
52+
def test_unmilled_flutter(unmilled_cover: Cover) -> None:
53+
"""Test an unmilled cover."""
54+
t_c = unmilled_cover.panel_flutter(mach=1.3, altitude=5000)
55+
assert isinstance(t_c, float)
56+
57+
58+
def test_unmilled_acoustic(unmilled_cover: Cover) -> None:
59+
"""Test an unmilled cover."""
60+
t_l, t_c = unmilled_cover.acoustic_fatigue()
61+
assert isinstance(t_l, float)
62+
assert isinstance(t_c, float)

0 commit comments

Comments
 (0)