loadpath 0.1.1__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.
- loadpath/README.md +294 -0
- loadpath/SKILL.md +584 -0
- loadpath/__init__.py +17 -0
- loadpath/__main__.py +1202 -0
- loadpath/am.py +316 -0
- loadpath/amgfast.py +326 -0
- loadpath/assembly.py +985 -0
- loadpath/benchmarks/__init__.py +0 -0
- loadpath/benchmarks/beams.py +266 -0
- loadpath/benchmarks/cases/ge-bracket.json +380 -0
- loadpath/benchmarks/evaluate.py +172 -0
- loadpath/benchmarks/mechanisms.py +416 -0
- loadpath/benchmarks/problems.py +140 -0
- loadpath/benchmarks/reference/bridge-3d.top3d.npz +0 -0
- loadpath/benchmarks/reference/cantilever-3d.top3d.npz +0 -0
- loadpath/benchmarks/reference/lbracket-2d.top88-ft2.npz +0 -0
- loadpath/benchmarks/reference/mbb-2d.top88-ft1.npz +0 -0
- loadpath/benchmarks/reference/mbb-2d.top88-ft2.npz +0 -0
- loadpath/benchmarks/reference.py +138 -0
- loadpath/benchmarks/run.py +301 -0
- loadpath/brep.py +1470 -0
- loadpath/bucklingopt.py +300 -0
- loadpath/buildsim.py +1490 -0
- loadpath/cadimport.py +904 -0
- loadpath/calibration.py +885 -0
- loadpath/cavities.py +211 -0
- loadpath/checks/__init__.py +0 -0
- loadpath/checks/dfm.py +354 -0
- loadpath/checks/exchanger.py +7 -0
- loadpath/checks/fea.py +212 -0
- loadpath/checks/fit.py +475 -0
- loadpath/checks/networks.py +260 -0
- loadpath/checks/opening.py +67 -0
- loadpath/checks/sdf_kit.py +7 -0
- loadpath/conjugate.py +267 -0
- loadpath/constrained.py +329 -0
- loadpath/contact.py +691 -0
- loadpath/coopt.py +342 -0
- loadpath/cores.py +163 -0
- loadpath/crease.py +1138 -0
- loadpath/critic.py +212 -0
- loadpath/crosscheck.py +1107 -0
- loadpath/cutcell.py +510 -0
- loadpath/data/lattice_buckling.json +439 -0
- loadpath/data/lattice_tensors.json +27449 -0
- loadpath/data/published_experiments.json +71 -0
- loadpath/decimate.py +177 -0
- loadpath/delivery.py +190 -0
- loadpath/directions.py +262 -0
- loadpath/domain.py +630 -0
- loadpath/drains.py +615 -0
- loadpath/durability.py +413 -0
- loadpath/editor.html +3135 -0
- loadpath/editor.py +610 -0
- loadpath/escape.py +354 -0
- loadpath/evals/__init__.py +0 -0
- loadpath/evals/baselines/coarse.json +1543 -0
- loadpath/evals/baselines/full.json +1497 -0
- loadpath/evals/brief_kinds/__init__.py +1 -0
- loadpath/evals/brief_kinds/heatx.py +387 -0
- loadpath/evals/brief_kinds/lattice.py +571 -0
- loadpath/evals/brief_kinds/multimat.py +593 -0
- loadpath/evals/briefs/assets/bracket.step +1201 -0
- loadpath/evals/briefs/assets/desk_arm.urdf +22 -0
- loadpath/evals/briefs/assets/elbow-gearbox.stl +0 -0
- loadpath/evals/briefs/assets/motor-body.stl +0 -0
- loadpath/evals/briefs/assets/sketch.png +0 -0
- loadpath/evals/briefs/base-adapter-fdm.json +492 -0
- loadpath/evals/briefs/bell-crank-lpbf.json +180 -0
- loadpath/evals/briefs/belt-tensioner-fdm.json +151 -0
- loadpath/evals/briefs/camera-boom-mjf.json +339 -0
- loadpath/evals/briefs/camera-mount-pla.json +203 -0
- loadpath/evals/briefs/coolant-isolator-petg.json +100 -0
- loadpath/evals/briefs/elbow-bearing-bracket-sls.json +300 -0
- loadpath/evals/briefs/elbow-gearbox-forearm-mjf.json +558 -0
- loadpath/evals/briefs/elbow-link-fatigue-fdm.json +251 -0
- loadpath/evals/briefs/elbow-stop-pad-tpu.json +39 -0
- loadpath/evals/briefs/forearm-fdm.json +146 -0
- loadpath/evals/briefs/forearm-servo-link-fdm.json +327 -0
- loadpath/evals/briefs/grip-pad-finger-mm.json +354 -0
- loadpath/evals/briefs/gripper-bracket-creep-fdm.json +340 -0
- loadpath/evals/briefs/gripper-finger-fdm.json +155 -0
- loadpath/evals/briefs/gripper-jaw-fatigue-mjf.json +328 -0
- loadpath/evals/briefs/gripper-palm-fdm.json +715 -0
- loadpath/evals/briefs/hot-stepper-mount-asa-fdm.json +471 -0
- loadpath/evals/briefs/hpu-oil-cooler-lpbf.json +121 -0
- loadpath/evals/briefs/isolated-camera-mount-mm.json +675 -0
- loadpath/evals/briefs/kart-charge-cooler-lpbf.json +93 -0
- loadpath/evals/briefs/lighten-step-bracket.json +220 -0
- loadpath/evals/briefs/nema17-mount-stl.json +429 -0
- loadpath/evals/briefs/pillow-block-sls.json +220 -0
- loadpath/evals/briefs/polyjet-fingertip-mm.json +305 -0
- loadpath/evals/briefs/rod-hook-pla.json +154 -0
- loadpath/evals/briefs/sensor-arm-resin.json +150 -0
- loadpath/evals/briefs/shelf-bracket-pla.json +158 -0
- loadpath/evals/briefs/shoulder-riser-mjf.json +487 -0
- loadpath/evals/briefs/sketch-clevis.json +229 -0
- loadpath/evals/briefs/spring-bracket-pacf.json +294 -0
- loadpath/evals/briefs/tool-flange-ti64.json +280 -0
- loadpath/evals/briefs/tray-arm-lattice-fdm.json +260 -0
- loadpath/evals/briefs/turret-fdm.json +281 -0
- loadpath/evals/briefs/upper-arm-sls.json +179 -0
- loadpath/evals/briefs/urdf-forearm.json +233 -0
- loadpath/evals/briefs/wrist-link-mjf.json +278 -0
- loadpath/evals/briefs/wrist-yoke-mjf.json +245 -0
- loadpath/evals/briefs.py +393 -0
- loadpath/evals/cases/arm-link-cast.json +157 -0
- loadpath/evals/cases/arm-link-driven.json +171 -0
- loadpath/evals/cases/arm-link-sandwich.json +315 -0
- loadpath/evals/cases/arm-link.json +111 -0
- loadpath/evals/cases/bell-crank.json +116 -0
- loadpath/evals/cases/grip-turret.json +479 -0
- loadpath/evals/cases/grip-upper-arm.json +253 -0
- loadpath/evals/cases/grip-wrist-link-mjf.json +929 -0
- loadpath/evals/cases/grip-wrist-yoke.json +831 -0
- loadpath/evals/cases/lpbf-intercooler-core.json +59 -0
- loadpath/evals/cases/mbb-beam.json +61 -0
- loadpath/evals/cases/motor-body.stl +0 -0
- loadpath/evals/cases/motor-mount.json +265 -0
- loadpath/evals/cases/printed-hook.json +77 -0
- loadpath/evals/cases/wall-bracket-fasteners.json +125 -0
- loadpath/evals/cases/wall-bracket.json +126 -0
- loadpath/evals/corpus.py +179 -0
- loadpath/evals/pareto.py +90 -0
- loadpath/evals/run.py +860 -0
- loadpath/examples/arm-link.json +25 -0
- loadpath/examples/bumpered-bracket-compression.json +225 -0
- loadpath/examples/bumpered-bracket-lattice.json +204 -0
- loadpath/examples/bumpered-bracket.json +34 -0
- loadpath/examples/gripper-finger-mm.json +185 -0
- loadpath/examples/heat-exchanger-counterflow.json +21 -0
- loadpath/examples/heat-exchanger-crossflow-tuned.json +48 -0
- loadpath/examples/heat-exchanger-crossflow.json +20 -0
- loadpath/examples/pedal-lattice.json +23 -0
- loadpath/examples/pressure-plenum.json +12 -0
- loadpath/examples/shelf-bracket.json +27 -0
- loadpath/exchanger.py +831 -0
- loadpath/fasteners.py +199 -0
- loadpath/fem.py +668 -0
- loadpath/femops.py +70 -0
- loadpath/fieldjit.py +981 -0
- loadpath/fieldops.py +119 -0
- loadpath/fields.py +3697 -0
- loadpath/fieldtorch.py +464 -0
- loadpath/flow.py +984 -0
- loadpath/flowtopo.py +300 -0
- loadpath/gpu.py +521 -0
- loadpath/heatx.py +1067 -0
- loadpath/heatx_thermal.py +432 -0
- loadpath/homogenized.py +886 -0
- loadpath/ibrep.py +552 -0
- loadpath/impact.py +693 -0
- loadpath/infill.py +376 -0
- loadpath/interface_library.py +340 -0
- loadpath/interlock.py +186 -0
- loadpath/isolator.py +149 -0
- loadpath/knn.py +204 -0
- loadpath/lattice.py +1065 -0
- loadpath/lattice3mf.py +760 -0
- loadpath/lattice_buckling.py +245 -0
- loadpath/lattice_grade.py +325 -0
- loadpath/lattice_orient.py +595 -0
- loadpath/lattice_print.py +159 -0
- loadpath/lattice_tensors.py +558 -0
- loadpath/latticestep.py +1210 -0
- loadpath/manufacture.py +446 -0
- loadpath/material_library.py +489 -0
- loadpath/materials.py +144 -0
- loadpath/mcp_server.py +786 -0
- loadpath/mechanism.py +218 -0
- loadpath/mechanism_nl.py +811 -0
- loadpath/meshops.py +452 -0
- loadpath/mg.py +853 -0
- loadpath/mma.py +214 -0
- loadpath/modal.py +210 -0
- loadpath/multimat.py +1788 -0
- loadpath/narrowband.py +418 -0
- loadpath/nlkernel.py +241 -0
- loadpath/nonlinear.py +1095 -0
- loadpath/orient.py +334 -0
- loadpath/porous.py +994 -0
- loadpath/pressure.py +171 -0
- loadpath/preview.py +335 -0
- loadpath/printcheck.py +263 -0
- loadpath/printsetup.py +207 -0
- loadpath/processcheck.py +376 -0
- loadpath/quick.py +113 -0
- loadpath/recall.py +406 -0
- loadpath/reconstruct.py +797 -0
- loadpath/render.py +436 -0
- loadpath/resolved.py +189 -0
- loadpath/schema.py +1701 -0
- loadpath/sdf_kit.py +843 -0
- loadpath/selfx.py +292 -0
- loadpath/shapes.py +584 -0
- loadpath/sharp.py +717 -0
- loadpath/simp.py +1170 -0
- loadpath/sizing.py +312 -0
- loadpath/slicer.py +321 -0
- loadpath/spec.py +1072 -0
- loadpath/step.py +806 -0
- loadpath/struts.py +639 -0
- loadpath/study.py +1937 -0
- loadpath/tasks.py +822 -0
- loadpath/thermal.py +1691 -0
- loadpath/threemf.py +487 -0
- loadpath/tune.py +437 -0
- loadpath/validation.py +145 -0
- loadpath/verify.py +1215 -0
- loadpath/viewer.html +694 -0
- loadpath/viewer.py +446 -0
- loadpath/viscoelastic.py +106 -0
- loadpath/voxelprint.py +582 -0
- loadpath/voxels.py +402 -0
- loadpath-0.1.1.dist-info/METADATA +319 -0
- loadpath-0.1.1.dist-info/RECORD +220 -0
- loadpath-0.1.1.dist-info/WHEEL +5 -0
- loadpath-0.1.1.dist-info/entry_points.txt +2 -0
- loadpath-0.1.1.dist-info/licenses/LICENSE +21 -0
- loadpath-0.1.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"""
|
|
2
|
+
As-printed lattice stiffness: how much softer a printed lattice is than its
|
|
3
|
+
designed geometry, by process, cell family and density, fitted to published
|
|
4
|
+
compression tests.
|
|
5
|
+
|
|
6
|
+
Checked against 33 printed lattices (validation.py,
|
|
7
|
+
data/published_experiments.json), loadpath's homogenized check reads the
|
|
8
|
+
designed geometry 1.0-4.1x stiffer than the prints measured (median 1.68x
|
|
9
|
+
either way), and its resolved voxel solve agrees with the homogenized one, so
|
|
10
|
+
the gap is the print, not the model: walls and struts thinner and rougher
|
|
11
|
+
than drawn, porous, stair-stepped, weakly bonded, and (in the tests) modulus
|
|
12
|
+
read from crosshead travel. The factor here is
|
|
13
|
+
|
|
14
|
+
k = 1 / exp(a_process + b_strut [strut cell] + c ln(rho / 0.2))
|
|
15
|
+
|
|
16
|
+
with rho the lattice's relative density (clipped to the tested 0.1-0.4 for
|
|
17
|
+
the density term) and k capped at 1: the check never reads a lattice stiffer
|
|
18
|
+
than designed. The density term says the prints stiffen more slowly with
|
|
19
|
+
density than the design does (the papers' denser lattices are the
|
|
20
|
+
over-predicted ones); the strut term that strut cells lose more than sheets.
|
|
21
|
+
|
|
22
|
+
Fitted coefficients (bench/lattice_print_fit.py, least squares on log
|
|
23
|
+
modulus ratio over all 33 specimens, results in
|
|
24
|
+
bench/results/lattice-print-fit.json):
|
|
25
|
+
|
|
26
|
+
process group exp(a) from
|
|
27
|
+
fdm 1.54 Shevchenko 2023 (PLA sheets), Guerra Silva 2021 (ABS, PC struts)
|
|
28
|
+
sls 1.08 Shevchenko 2023 (PA12 sheets), Abou-Ali 2022 (PA11 sheets and struts)
|
|
29
|
+
resin 1.33 Shevchenko 2023 (LCD resin sheets)
|
|
30
|
+
strut cells x1.58
|
|
31
|
+
density x1.34 per e-fold of rho / 0.2
|
|
32
|
+
|
|
33
|
+
Held out (each specimen predicted from a fit to the other 32), the median
|
|
34
|
+
error in modulus falls from 1.68x to 1.23x (worst 4.12x to 2.04x); leaving
|
|
35
|
+
out a whole paper, its specimens read a median 0.92-1.17x of the measurement. Per-cell-type terms (Schwarz P,
|
|
36
|
+
Kelvin, octet) did not improve the held-out error and are not used.
|
|
37
|
+
|
|
38
|
+
Process groups: mjf is read as sls (no MJF lattice tests found), sla and dlp
|
|
39
|
+
as the LCD resin. volumetric, jetting and lpbf have no printed-lattice data
|
|
40
|
+
here: their factor is None and the check reads the designed geometry, with
|
|
41
|
+
a note.
|
|
42
|
+
|
|
43
|
+
Strength: a sheet print fails at about the strain its design predicts for
|
|
44
|
+
first yield, not the stress (the PLA Schwarz P lattice that broke at 0.84x
|
|
45
|
+
its predicted first-yield stress is 2.4x softer than the same geometry in
|
|
46
|
+
SLS PA12 and failed at the same strain), so for sheets the homogenized
|
|
47
|
+
check reads wall stress from the strain the softer lattice takes. Strut
|
|
48
|
+
lattices read from the macro stress they carry: their first yield was safe
|
|
49
|
+
that way on every strut specimen, and the strain reading made FDM strut
|
|
50
|
+
lattices 2.5x more conservative than they need (STRAIN_SHARE). Held out,
|
|
51
|
+
first yield is under the measured strength on all 33 specimens.
|
|
52
|
+
|
|
53
|
+
A calibrated card (calibration.py, gyroid coupon L-GY) that measured its own
|
|
54
|
+
lattice stiffness factor replaces this fit; so does a study's
|
|
55
|
+
process.latticeStiffness (a number, or "designed").
|
|
56
|
+
"""
|
|
57
|
+
from __future__ import annotations
|
|
58
|
+
|
|
59
|
+
import numpy as np
|
|
60
|
+
|
|
61
|
+
__all__ = ["STRAIN_SHARE", "strain_share", "PRINT_FIT", "PROCESS_GROUP", "print_factor", "process_group", "features", "fit", "fit_rows"]
|
|
62
|
+
|
|
63
|
+
# bench/lattice_print_fit.py writes these (tests/test_lattice_print.py checks
|
|
64
|
+
# they match a refit of bench/results/published-experiments.json)
|
|
65
|
+
PRINT_FIT = {
|
|
66
|
+
"intercept": {"fdm": 0.43111, "sls": 0.07451, "resin": 0.2811},
|
|
67
|
+
"strut": 0.45728,
|
|
68
|
+
"densitySlope": 0.29423,
|
|
69
|
+
"rhoRef": 0.2,
|
|
70
|
+
"rhoRange": [0.1, 0.4],
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# How the check reads wall stress in a softer printed lattice: 1 = from the
|
|
74
|
+
# strain it takes (stress k^-1 higher than the carried macro stress says),
|
|
75
|
+
# 0 = from the stress it carries. Chosen per family as the least value that
|
|
76
|
+
# keeps every published specimen's first-yield reading under its measured
|
|
77
|
+
# strength, then held out a paper at a time (bench/lattice_print_fit.py):
|
|
78
|
+
# - sheets 1: the FDM PLA Schwarz P lattice needs it (1.19x at 0, 0.82x at
|
|
79
|
+
# 1). With Shevchenko 2023 held out the rest of the data asks for 0, and
|
|
80
|
+
# that paper's PLA P then reads 1.19x, so the sheet value rests on one
|
|
81
|
+
# paper and the physical reading (the PLA print failed at the strain its
|
|
82
|
+
# design yields at, 2.4x softer than the same geometry in SLS);
|
|
83
|
+
# - struts 0: safe on all 20 strut specimens (0.18-0.91x), and with either
|
|
84
|
+
# strut paper held out the other still asks for 0 and reads safe on it
|
|
85
|
+
# (Abou-Ali 0.65-0.91x, Guerra Silva 0.18-0.78x). At 1 the FDM strut
|
|
86
|
+
# lattices read 0.07-0.41x of their plateau.
|
|
87
|
+
STRAIN_SHARE = {"sheet": 1.0, "strut": 0.0}
|
|
88
|
+
|
|
89
|
+
PROCESS_GROUP = {"fdm": "fdm", "sls": "sls", "mjf": "sls", "sla": "resin", "dlp": "resin"}
|
|
90
|
+
|
|
91
|
+
SOURCES = {
|
|
92
|
+
"fdm": ["shevchenko2023", "guerrasilva2021"],
|
|
93
|
+
"sls": ["shevchenko2023", "abouali2022"],
|
|
94
|
+
"resin": ["shevchenko2023"],
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
FEATURES = ("fdm", "sls", "resin", "strut", "lrho")
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def strain_share(lattice_kind: str) -> float:
|
|
101
|
+
from .struts import is_strut
|
|
102
|
+
|
|
103
|
+
return STRAIN_SHARE["strut" if is_strut(lattice_kind) else "sheet"]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def process_group(kind: str | None) -> str | None:
|
|
107
|
+
return PROCESS_GROUP.get(str(kind).lower()) if kind else None
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def features(group: str, strut: bool, rho, rho_ref: float = 0.2, rho_range=(0.1, 0.4)) -> np.ndarray:
|
|
111
|
+
"""Design rows (n, 5) for the fit: one-hot process group, strut flag,
|
|
112
|
+
log density over the reference (clipped to the tested range)."""
|
|
113
|
+
rho = np.atleast_1d(np.asarray(rho, float))
|
|
114
|
+
x = np.zeros((len(rho), len(FEATURES)))
|
|
115
|
+
x[:, FEATURES.index(group)] = 1.0
|
|
116
|
+
x[:, 3] = float(bool(strut))
|
|
117
|
+
x[:, 4] = np.log(np.clip(rho, *rho_range) / rho_ref)
|
|
118
|
+
return x
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def print_factor(process_kind: str | None, lattice_kind: str, rho, fit_: dict | None = None):
|
|
122
|
+
"""As-printed stiffness over designed (<= 1) at relative densities rho,
|
|
123
|
+
or None where the process has no printed-lattice data."""
|
|
124
|
+
from .struts import is_strut
|
|
125
|
+
|
|
126
|
+
group = process_group(process_kind)
|
|
127
|
+
if group is None:
|
|
128
|
+
return None
|
|
129
|
+
f = fit_ or PRINT_FIT
|
|
130
|
+
b = np.array([f["intercept"]["fdm"], f["intercept"]["sls"], f["intercept"]["resin"], f["strut"],
|
|
131
|
+
f["densitySlope"]])
|
|
132
|
+
x = features(group, is_strut(lattice_kind), rho, f["rhoRef"], tuple(f["rhoRange"]))
|
|
133
|
+
return np.minimum(np.exp(-(x @ b)), 1.0)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def fit_rows(results: dict) -> list[dict]:
|
|
137
|
+
"""Rows for the fit from bench/results/published-experiments.json: group,
|
|
138
|
+
strut flag, rho, the homogenized and measured modulus and strength."""
|
|
139
|
+
from .struts import is_strut
|
|
140
|
+
from .validation import process_kind
|
|
141
|
+
|
|
142
|
+
rows = []
|
|
143
|
+
for sid, r in results.items():
|
|
144
|
+
rows.append({"id": sid, "source": r["source"], "group": process_group(process_kind(r["process"])),
|
|
145
|
+
"strut": bool(is_strut(r["lattice"]["type"])), "type": r["lattice"]["type"],
|
|
146
|
+
"rho": float(r["table"]["rho"]), "E": float(r["homogenized"]["E"]),
|
|
147
|
+
"Emeas": float(r["measured"]["E"]), "firstYield": float(r["homogenized"]["firstYield"]),
|
|
148
|
+
"strength": float(r["measured"]["strength"])})
|
|
149
|
+
return rows
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def fit(rows: list[dict], ridge: float = 1e-3) -> dict:
|
|
153
|
+
"""Least squares of log(designed / measured modulus) on the features
|
|
154
|
+
(a light ridge keeps a group missing from `rows` at zero)."""
|
|
155
|
+
x = np.vstack([features(r["group"], r["strut"], r["rho"]) for r in rows])
|
|
156
|
+
y = np.log([r["E"] / r["Emeas"] for r in rows])
|
|
157
|
+
b = np.linalg.solve(x.T @ x + ridge * np.eye(x.shape[1]), x.T @ y)
|
|
158
|
+
return {"intercept": {"fdm": float(b[0]), "sls": float(b[1]), "resin": float(b[2])}, "strut": float(b[3]),
|
|
159
|
+
"densitySlope": float(b[4]), "rhoRef": 0.2, "rhoRange": [0.1, 0.4]}
|