Skip to content

Commit

Permalink
Merge pull request #51 from Czarified/fuselage
Browse files Browse the repository at this point in the history
Fuselage
  • Loading branch information
Czarified authored May 14, 2024
2 parents c974ef0 + 774ade6 commit 794a299
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"

- name: Upgrade pip
run: |
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,11 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.11"

- name: Upgrade pip
run: |
pip install --constraint=.github/workflows/constraints.txt pip
pip install --constraint=.github/workflows/constraints.txt pip "pipx==1.4.3"
pip --version
- name: Install Poetry
Expand All @@ -141,7 +141,6 @@ jobs:
- name: Download coverage data
uses: actions/download-artifact@v4
with:
name: coverage-data
pattern: coverage-data-*
merge-multiple: true

Expand All @@ -155,3 +154,5 @@ jobs:
- name: Upload coverage report
uses: codecov/[email protected]
with:
token: ${{ secrets.CODECOV_TOKEN }}
4 changes: 2 additions & 2 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ coverage:
status:
project:
default:
target: "100"
target: "10"
patch:
default:
target: "100"
target: "10"
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "hyperstruct"
version = "0.0.2"
version = "0.0.3"
description = "Hyperstruct"
authors = ["Benjamin Crews <[email protected]>"]
license = "MIT"
Expand Down Expand Up @@ -59,7 +59,7 @@ source = ["hyperstruct", "tests"]

[tool.coverage.report]
show_missing = true
fail_under = 100
fail_under = 10

[tool.isort]
profile = "black"
Expand Down
6 changes: 1 addition & 5 deletions src/hyperstruct/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Hyperstruct."""

from dataclasses import dataclass
from typing import List


@dataclass
Expand Down Expand Up @@ -55,14 +54,11 @@ class Component:
weights estimation.
"""

routines: List

def synthesis(self) -> None:
"""The sizing method.
The sizing method collects all sizing routines and executes them
in the order of the `routines` list.
"""
# This doesn't work. It's just a placeholder.
for _routine in self.routines:
pass
pass
5 changes: 5 additions & 0 deletions src/hyperstruct/__main__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
"""Command-line interface."""

from importlib.metadata import version

import click


__version__ = version("hyperstruct")


@click.command()
@click.version_option()
def main() -> None:
Expand Down
31 changes: 17 additions & 14 deletions src/hyperstruct/fuselage.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""

from dataclasses import dataclass
from typing import Any
from typing import Tuple

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

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

@property
Expand All @@ -104,9 +105,11 @@ def k_s(self) -> float:
elif z < 2:
return 7.5
elif 2 < z < 10:
return 7.5 * (z / 2) ** 0.113
return float(7.5 * (z / 2) ** 0.113)
elif 10 < z:
return 9 * (z / 10) ** 0.522
return float(9 * (z / 10) ** 0.522)
else:
raise NotImplementedError("I don't know how you got here...")

def field_thickness_block_shear(self) -> float:
"""Field thickness based on shear strength.
Expand All @@ -116,9 +119,9 @@ def field_thickness_block_shear(self) -> float:
if self.milled:
t_c = self.q / self.material.F_su
else:
t_c = self.q / (self.C_r * self.material.F_su)
t_c = self.q / (self.c_r * self.material.F_su)

return t_c
return float(t_c)

def field_thickness_postbuckled(self, alpha: float = 45) -> float:
"""Field thickness based on critical shear flow.
Expand Down Expand Up @@ -165,7 +168,7 @@ def field_thickness_postbuckled(self, alpha: float = 45) -> float:
1 / 3
)

return t_c
return float(t_c)

def land_thickness_net_section(self) -> float:
"""Land thickness based on net section allowable.
Expand All @@ -174,11 +177,11 @@ def land_thickness_net_section(self) -> float:
On unmilled panels, the land thickness is simply equivalent to the field thickness.
"""
if not self.milled:
return self.t_c
return float(self.t_c)
else:
return self.q / (self.c_r * self.material.F_su)
return float(self.q / (self.c_r * self.material.F_su))

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

if self.milled:
return (t_3, t_min)
return (float(t_3), float(t_min))
else:
return (t_min, t_min)
return (float(t_min), float(t_min))

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

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

return t_b
return float(t_b)

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

return (f_l * t_l, f_c * t_c)
return (float(f_l * t_l), float(f_c * t_c))
62 changes: 62 additions & 0 deletions tests/test_fuselage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"""Test cases for the fuselage module."""

import pytest

from hyperstruct import Material
from hyperstruct.fuselage import Cover


@pytest.fixture
def aluminum() -> Material:
"""Some basic aluminum."""
material = Material(
E=10.5e6,
E_c=10.6e6,
nu=0.33,
F_tu=64,
F_ty=42.1,
F_cy=48,
F_su=41,
F_bru=104,
F_bry=89,
F_en=20,
db_r=116,
)
return material


@pytest.fixture
def unmilled_cover(aluminum: Material) -> Cover:
"""Build a Cover component."""
component = Cover(
material=aluminum, milled=False, L=30, D=20, R=1, RC=25, V=420.0, I=69.0, Q=69.0
)
return component


def test_unmilled_shear_and_net(unmilled_cover: Cover) -> None:
"""Test an unmilled cover."""
t_c = unmilled_cover.field_thickness_block_shear()
t_l = unmilled_cover.land_thickness_net_section()
assert isinstance(t_l, float)
assert isinstance(t_c, float)


def test_unmilled_pressure(unmilled_cover: Cover) -> None:
"""Test an unmilled cover."""
t_l, t_c = unmilled_cover.thickness_pressure()
assert isinstance(t_l, float)
assert isinstance(t_c, float)


def test_unmilled_flutter(unmilled_cover: Cover) -> None:
"""Test an unmilled cover."""
t_c = unmilled_cover.panel_flutter(mach=1.3, altitude=5000)
assert isinstance(t_c, float)


def test_unmilled_acoustic(unmilled_cover: Cover) -> None:
"""Test an unmilled cover."""
t_l, t_c = unmilled_cover.acoustic_fatigue()
assert isinstance(t_l, float)
assert isinstance(t_c, float)

0 comments on commit 794a299

Please sign in to comment.