WillTools 2026-09-09 -- clean snapshot of the development repo for review
ci / test (push) Successful in 6m14s

History-free snapshot of the private development repository at 77a82eb.
Code, docs and the public catalogue only: no plant or job knowledge
layers, no client, job or producer names (tools/scrub.py clean against
the widened term list; a second word-level grep clean). The intro deck is
left out because its slide images cannot be checked for job drawings.
This commit is contained in:
2026-09-09 08:35:15 -05:00
commit 25592fa6c2
406 changed files with 223435 additions and 0 deletions
+141
View File
@@ -0,0 +1,141 @@
# -*- coding: utf-8 -*-
"""The two worked examples from ASPIRE Winter 2019, end to end.
Every number asserted here appears in print in the article. Where our model is
deliberately more refined than the article -- it reduces the self weight for
the pockets, which the article says it neglects -- the difference is asserted
in the direction it must go, rather than papered over with a loose tolerance.
"""
from panellift import pci, section, statics
from panellift.model import Stage
from conftest import ASPIRE
def _stress_psi(moment_lbft, s_in3):
return moment_lbft * 12.0 / s_in3
# ------------------------------------------------------- section properties
def test_solid_section_modulus(solid_panel):
s = section.section_modulus_in3(solid_panel, 16.0)
assert abs(s - ASPIRE['s_solid_in3']) < 1.0
def test_pocketed_section_modulus(pocketed_panel):
"""Five 6 in. pockets in one row: 1148 in^3, printed in the article."""
x = pocketed_panel.blockouts[0].x0 + 1.0
s = section.section_modulus_in3(pocketed_panel, x)
assert abs(s - ASPIRE['s_pocketed_in3']) < 1.0
def test_pockets_only_reduce_the_section_where_they_are(pocketed_panel):
away = section.section_modulus_in3(pocketed_panel, 16.0)
assert abs(away - ASPIRE['s_solid_in3']) < 1.0
# ------------------------------------------------------------- allowables
def test_allowable_tension_at_stripping():
assert abs(pci.allowable_tension_psi(4000.0) -
ASPIRE['strip_allowable_psi']) < 1.0
def test_allowable_tension_at_shipping():
assert abs(pci.allowable_tension_psi(5000.0) -
ASPIRE['ship_allowable_psi']) < 1.0
def test_table_831_multipliers():
assert pci.stripping_multiplier('flat', 'smooth') == 1.3
assert pci.stripping_multiplier('flat', 'exposed') == 1.2
assert pci.stripping_multiplier('sculptured', 'smooth') == 1.7
assert pci.TRANSPORTATION_MULTIPLIER == 1.5
assert pci.YARD_AND_ERECTION_MULTIPLIER == 1.2
# --------------------------------------------------- example 1, solid panel
def test_example_1_stripping(solid_panel, stripping, rolling):
"""1.3 x 23,973 lb-ft over S = 1531 in^3 gives 244 psi, under 316 psi."""
result = statics.analyse(solid_panel, stripping, rolling,
reconcile_weight=False)
_, moment = result.diagram.max_positive
stress = _stress_psi(moment, ASPIRE['s_solid_in3'])
assert abs(stress - ASPIRE['strip_stress_psi']) < 3.0
assert stress < pci.allowable_tension_psi(4000.0)
def test_example_1_shipping(solid_panel, shipping, rolling):
"""1.5 x 23,973 lb-ft over S = 1531 in^3 gives 282 psi, under 354 psi."""
result = statics.analyse(solid_panel, shipping, rolling,
reconcile_weight=False)
_, moment = result.diagram.max_positive
stress = _stress_psi(moment, ASPIRE['s_solid_in3'])
assert abs(stress - ASPIRE['ship_stress_psi']) < 3.0
assert stress < pci.allowable_tension_psi(5000.0)
# ------------------------------------------------ example 2, with pockets
def test_example_2_stripping_fails_as_printed(solid_panel, stripping, rolling):
"""326 psi against 316 psi allowable. No good, says the article.
Computed the article's way: the solid-panel moment against the reduced
section, because the article explicitly neglects the weight the pockets
remove.
"""
result = statics.analyse(solid_panel, stripping, rolling,
reconcile_weight=False)
_, moment = result.diagram.max_positive
stress = _stress_psi(moment, ASPIRE['s_pocketed_in3'])
assert abs(stress - ASPIRE['pocketed_strip_stress_psi']) < 3.0
assert stress > pci.allowable_tension_psi(4000.0)
def test_example_2_shipping_fails_as_printed(solid_panel, shipping, rolling):
"""376 psi against 354 psi allowable."""
result = statics.analyse(solid_panel, shipping, rolling,
reconcile_weight=False)
_, moment = result.diagram.max_positive
stress = _stress_psi(moment, ASPIRE['s_pocketed_in3'])
assert abs(stress - ASPIRE['pocketed_ship_stress_psi']) < 3.0
assert stress > pci.allowable_tension_psi(5000.0)
def test_modelling_the_pocket_weight_relieves_the_moment_slightly(
pocketed_panel, solid_panel, stripping, rolling):
"""Our full model is less conservative than the article, and must say so.
The article neglects the 1.6% of self weight the pockets remove. We do
not, so our moment comes out slightly lower -- a few percent at most. If
that gap were ever large it would mean the blockouts were misread, so the
test pins the size of the difference, not just its sign.
"""
full = statics.analyse(pocketed_panel, stripping, rolling,
reconcile_weight=False)
article = statics.analyse(solid_panel, stripping, rolling,
reconcile_weight=False)
_, m_full = full.diagram.max_positive
_, m_article = article.diagram.max_positive
assert m_full < m_article
assert (m_article - m_full) / m_article < 0.05
def test_pocketed_panel_still_fails_when_modelled_fully(pocketed_panel,
stripping, rolling):
"""The refinement must not turn a printed failure into a pass."""
result = statics.analyse(pocketed_panel, stripping, rolling,
reconcile_weight=False)
x0 = pocketed_panel.blockouts[0].x0
x = x0 + 1.0
moment = abs(result.diagram.moment_at(x))
s = section.section_modulus_in3(pocketed_panel, x)
assert _stress_psi(moment, s) > pci.allowable_tension_psi(4000.0)