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,489 @@
|
|
|
1
|
+
"""
|
|
2
|
+
The material library: one card per material, every number with its source.
|
|
3
|
+
|
|
4
|
+
A study names a material ("petg", "pa12", "ti64"); materials.MATERIALS is
|
|
5
|
+
built from these cards, and so are thermal.CONDUCTIVITY and the across-
|
|
6
|
+
layer factors a card supplies to a layered process (spec.study_from_dict).
|
|
7
|
+
Each value is (number, source id, note); `SOURCES` says what each id is and
|
|
8
|
+
where to read it. The datasheets were read on 2026-10-30.
|
|
9
|
+
|
|
10
|
+
How a card is chosen. Each generic name takes its values from one named
|
|
11
|
+
datasheet, so the numbers on a card are consistent with each other (the
|
|
12
|
+
same printer, slicer profile and test). Brands differ more than the
|
|
13
|
+
anisotropy does: PETG's in-plane strength reads 47 MPa on Prusament's
|
|
14
|
+
sheet and 32 MPa on Polymaker's, and PLA's across-layer strength is 33% of
|
|
15
|
+
in-plane on Prusament's (an interlayer adhesion test) and 93% on
|
|
16
|
+
Polymaker's (a Z-printed tensile bar). docs/materials.md lists the spread.
|
|
17
|
+
A part that matters gets coupons printed and a calibrated card
|
|
18
|
+
(calibration.py), which overrides the library card of the same name.
|
|
19
|
+
|
|
20
|
+
What the code reads:
|
|
21
|
+
E, nu, strength, density every analysis (materials.Material)
|
|
22
|
+
strengthZ across-layer strength -> process.interlayer
|
|
23
|
+
EZ across-layer modulus -> process stiffnessAcrossLayers
|
|
24
|
+
conductivity thermal.CONDUCTIVITY (heat paths, thermal TO)
|
|
25
|
+
specificHeat J/(kg K) -> thermal.SPECIFIC_HEAT (heat-up and cool-down)
|
|
26
|
+
hdt heat deflection temperature at 0.45 MPa: the
|
|
27
|
+
temperature checks warn above it (durability)
|
|
28
|
+
cte thermal expansion, um/(m K) -> thermal.EXPANSION
|
|
29
|
+
retention modulus kept vs temperature -> thermal.MODULUS_RETENTION
|
|
30
|
+
(and, as a proxy, strength: durability)
|
|
31
|
+
The rest (elongation, Tg, hdt18, fatigue) is carried for the report and
|
|
32
|
+
for people; fatigue and creep design values live in durability.DURABILITY,
|
|
33
|
+
which cites its own literature.
|
|
34
|
+
|
|
35
|
+
Values a datasheet does not give are marked with the source "estimate"
|
|
36
|
+
(Poisson's ratio for polymers, mostly) and say why that number.
|
|
37
|
+
"""
|
|
38
|
+
from __future__ import annotations
|
|
39
|
+
|
|
40
|
+
from dataclasses import dataclass
|
|
41
|
+
|
|
42
|
+
__all__ = ["Source", "SOURCES", "LIBRARY", "card", "card_names", "value", "describe"]
|
|
43
|
+
|
|
44
|
+
ACCESSED = "2026-10-30"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass(frozen=True)
|
|
48
|
+
class Source:
|
|
49
|
+
title: str
|
|
50
|
+
url: str = ""
|
|
51
|
+
note: str = ""
|
|
52
|
+
|
|
53
|
+
def to_dict(self):
|
|
54
|
+
return {"title": self.title, "url": self.url, "note": self.note}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
SOURCES = {
|
|
58
|
+
"prusament-pla": Source(
|
|
59
|
+
"Prusament PLA technical datasheet, v1.1 (27-07-2022), Prusa Polymers",
|
|
60
|
+
"https://www.matterhackers.com/r/xFvGl8",
|
|
61
|
+
"ISO 527-1 on specimens printed on an Original Prusa i3 MK3, 100% rectilinear infill; "
|
|
62
|
+
"'Vertical xz' is printed on edge, not across layers; interlayer adhesion is Prusa's own test"),
|
|
63
|
+
"prusament-petg": Source(
|
|
64
|
+
"Prusament PETG technical datasheet, v1.1 (16-02-2022), Prusa Polymers",
|
|
65
|
+
"https://www.3dprintergear.com.au/assets/files/technical-data-sheet%20(1).pdf",
|
|
66
|
+
"as Prusament PLA"),
|
|
67
|
+
"polylite-abs": Source(
|
|
68
|
+
"Polymaker PolyLite ABS TDS v5.2",
|
|
69
|
+
"https://cdn.shopify.com/s/files/1/0789/2979/files/PolyLite_ABS_TDS_V5.2.pdf",
|
|
70
|
+
"ISO 527 printed X-Y and Z specimens, 100% infill"),
|
|
71
|
+
"polylite-asa": Source(
|
|
72
|
+
"Polymaker PolyLite ASA TDS v5.1",
|
|
73
|
+
"https://cdn.shopify.com/s/files/1/0603/6609/files/PolyLite_ASA_TDS_V5.1.pdf",
|
|
74
|
+
"ISO 527 printed X-Y and Z specimens, 100% infill"),
|
|
75
|
+
"ultimaker-tpu95a": Source(
|
|
76
|
+
"UltiMaker TPU 95A technical data sheet v2.01 (15-09-2025)",
|
|
77
|
+
"https://um-support-files.ultimaker.com/materials/2.85mm/tds/TPU-95A/TDS-TPU95A-V2.01-250915.pdf",
|
|
78
|
+
"ASTM D3039 printed XY / YZ / Z specimens"),
|
|
79
|
+
"bambu-paht-cf": Source(
|
|
80
|
+
"Bambu Lab PAHT-CF technical data sheet v2",
|
|
81
|
+
"https://uwaterloo.ca/rapid-prototyping-centre/sites/default/files/uploads/documents/"
|
|
82
|
+
"bambu_paht-cf_technical_data_sheet_v2.pdf",
|
|
83
|
+
"ISO 527, dry state, printed X-Y and Z specimens, 100% infill"),
|
|
84
|
+
"hp-5200-whitepaper": Source(
|
|
85
|
+
"HP 3D Printing materials for the HP Jet Fusion 5200 Series: Mechanical Properties (white paper)",
|
|
86
|
+
"https://info.sculpteo.com/hubfs/Material%20documentation/PA11%20HP/"
|
|
87
|
+
"TDS%20HP%20pa12%20pa12gb%20pa11%20pp%20(1).pdf",
|
|
88
|
+
"ASTM D638 Type I, Balanced print profile, 349-part test job, XY and Z averages"),
|
|
89
|
+
"eos-pa3200gf": Source(
|
|
90
|
+
"EOS PA 3200 GF material data sheet, status 30.08.2026",
|
|
91
|
+
"https://www.indus3design.com/wp-content/uploads/2026/08/i3d-datasheets-eos-pa-3200-gf.pdf",
|
|
92
|
+
"laser sintered; ISO 527-1/-2 X and Z orientations, ISO 75 HDT"),
|
|
93
|
+
"basf-tpu88a": Source(
|
|
94
|
+
"BASF Forward AM Ultrasint TPU 88A technical data sheet v2.2 (08/2021)",
|
|
95
|
+
"https://3dprinting.rpamerica.us/hubfs/BASF/UltrasintTM%20TPU%20Line.pdf",
|
|
96
|
+
"laser sintered; DIN 53504 S2 tensile, ISO 527-2 1A modulus, X and Z"),
|
|
97
|
+
"formlabs-standard": Source(
|
|
98
|
+
"Formlabs Standard Resins (Clear, White, Grey, Black) material properties, Rev 02 (14-08-2023)",
|
|
99
|
+
"https://8baht.com/storage/product_dowloads/65d4b84c383c5.pdf",
|
|
100
|
+
"ASTM D638-14, Form 2 at 100 um, post-cured; Grey V4"),
|
|
101
|
+
"formlabs-tough2000": Source(
|
|
102
|
+
"Formlabs Tough 2000 Resin technical data sheet V1, Rev 01 (10-07-2020)",
|
|
103
|
+
"https://cdn.goengineer.com/formlabs-tough-2000-resin-technical-data-sheet.pdf",
|
|
104
|
+
"ASTM D638-14, Form 2 at 100 um, post-cured 120 min at 80 C"),
|
|
105
|
+
"formlabs-rigid10k": Source(
|
|
106
|
+
"Formlabs Rigid 10K Resin technical data sheet, Rev 01 (06-09-2020)",
|
|
107
|
+
"https://core-electronics.com.au/attachments/rigid10k-TDS-ENUS-0.pdf",
|
|
108
|
+
"ASTM D638-14, UV post-cure column (60 min at 70 C)"),
|
|
109
|
+
"stratasys-vero": Source(
|
|
110
|
+
"Stratasys PolyJet Vero (Rigid Opaque) material data sheet (VeroWhitePlus, VeroBlackPlus, VeroGray, "
|
|
111
|
+
"Vero PureWhite, VeroVivid...), hosted by GoEngineer",
|
|
112
|
+
"https://cdn.goengineer.com/stratasys_polyjet_vero-material-data-sheet.pdf",
|
|
113
|
+
"ASTM D638 / D790 / D648 ranges for the family; printed, as built"),
|
|
114
|
+
"stratasys-agilus30": Source(
|
|
115
|
+
"Stratasys PolyJet Agilus30 material data sheet (Black / Translucent / White), hosted by GoEngineer",
|
|
116
|
+
"https://cdn.goengineer.com/stratasys-polyjet-agilus30-material-data-sheet.pdf",
|
|
117
|
+
"ASTM D412 tensile, D2240 hardness, D792 density; ranges per colour"),
|
|
118
|
+
"addup-alsi10mg": Source(
|
|
119
|
+
"AddUp AlSi10Mg material data sheet, version US-10252023-0129 (FormUp 350, 50 um layers)",
|
|
120
|
+
"https://addupsolutions.com/wp-content/uploads/2023/10/AlSi10Mg-Material-Data-Sheet.pdf",
|
|
121
|
+
"ASTM E8, machined specimens, as built, >= 27 samples across the plate"),
|
|
122
|
+
"addup-316l": Source(
|
|
123
|
+
"AddUp 316L SS material data sheet, version US-07172023-0134 (FormUp 350, 40 um layers)",
|
|
124
|
+
"https://addupsolutions.com/wp-content/uploads/2023/09/AddUp-316L-SS-Materials-Data-Sheet.pdf",
|
|
125
|
+
"ASTM E8, machined specimens, as built, >= 39 samples across the plate"),
|
|
126
|
+
"eos-ti64": Source(
|
|
127
|
+
"EOS Titanium Ti64 material data sheet (EOS M 290 400 W), 07.2022",
|
|
128
|
+
"https://www.eos.info/05-datasheet-images/Assets_MDS_Metal/EOS_Titanium_Ti64/"
|
|
129
|
+
"Material_DataSheet_EOS_Titanium_Ti64_EOSM290_EOSM300-4_EOSM400_EOSM400-4_en.pdf",
|
|
130
|
+
"ISO 6892-1; heat treated 800 C / 4 h in argon (the usual delivered state)"),
|
|
131
|
+
"eos-ti64-grade5": Source(
|
|
132
|
+
"EOS Titanium Ti64 Grade 5 material data sheet, status 01/2024",
|
|
133
|
+
"https://EOS.info/05-datasheet-images/Assets_MDS_Metal/EOS_Titanium_Ti64_Grade5/"
|
|
134
|
+
"material_datasheet_eos_titanium_ti64_grade5_en_web.pdf",
|
|
135
|
+
"fatigue strength at 1e7 cycles, heat treated, ISO 12107 statistics"),
|
|
136
|
+
"tychanicz-2025": Source(
|
|
137
|
+
"Tychanicz-Kwiecien et al. 2025, thermal conductivity of FDM-printed PLA and PETG "
|
|
138
|
+
"(as used by heatx_thermal.WALL_CONDUCTIVITY)", "", "dense printed parts, in plane"),
|
|
139
|
+
"eos-in625": Source(
|
|
140
|
+
"EOS NickelAlloy IN625 material data sheet (EOS M 290), 06.2022",
|
|
141
|
+
"https://uk.eos.info/03_system-related-assets/material-related-contents/metal-materials-and-examples/"
|
|
142
|
+
"metal-material-datasheet/nickelalloy-inconel/niall-in625-m290_material_data_sheet_06-22_en.pdf",
|
|
143
|
+
"ISO 6892-1, as built; the modulus is from EOS's general IN625 sheet (heat treated, 204 GPa Z / 214 XY)"),
|
|
144
|
+
"eos-ph1": Source(
|
|
145
|
+
"EOS StainlessSteel PH1 (15-5 PH) material data sheet (EOS M 290), 07.2022",
|
|
146
|
+
"https://www.eos.info/05-datasheet-images/Assets_MDS_Metal/EOS_StainlessSteel_PH1/"
|
|
147
|
+
"ss-ph1-m290_material_data_sheet_07-22_en.pdf",
|
|
148
|
+
"ISO 6892-1 Annex C, 20 um layers, as built"),
|
|
149
|
+
"handbook": Source(
|
|
150
|
+
"typical wrought/cast handbook value for the alloy (ASM Handbook class data)", "",
|
|
151
|
+
"used where the AM datasheet gives none; AM parts sit within a few percent"),
|
|
152
|
+
"polymer-handbook": Source(
|
|
153
|
+
"typical value for the polymer family (J. E. Mark, Physical Properties of Polymers Handbook, "
|
|
154
|
+
"2nd ed., Springer 2007)", "https://doi.org/10.1007/978-0-387-69002-5",
|
|
155
|
+
"unfilled bulk polymer; printing does not change the specific heat"),
|
|
156
|
+
"estimate": Source(
|
|
157
|
+
"loadpath estimate: no datasheet value", "",
|
|
158
|
+
"typical of the polymer family; replace with a calibrated card where it matters"),
|
|
159
|
+
"dma-estimate": Source(
|
|
160
|
+
"loadpath estimate: read off typical DMA storage-modulus curves for the polymer family and its heat "
|
|
161
|
+
"deflection temperature", "",
|
|
162
|
+
"approximate; the cliff at the glass transition is where sources disagree most. Measure it "
|
|
163
|
+
"(DMA, or a heated cantilever) if a part runs warm"),
|
|
164
|
+
"durability": Source("durability.DURABILITY (fatigue and creep design values, cited there)"),
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
# (value, source id, note)
|
|
168
|
+
def _c(title, processes, measured=None, **values):
|
|
169
|
+
"""A card. `measured`: the process the datasheet's specimens were made
|
|
170
|
+
by (default the first of `processes`); its across-layer values apply to
|
|
171
|
+
studies printed by that process only."""
|
|
172
|
+
return {"title": title, "processes": tuple(processes), "measured": measured or processes[0],
|
|
173
|
+
"values": values}
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
_RET = "(C, share of the 23 C modulus), piecewise linear; past the last point the last value holds"
|
|
177
|
+
_NU_POLY = (0.36, "estimate", "datasheets don't list it; 0.35-0.40 is typical of glassy thermoplastics")
|
|
178
|
+
|
|
179
|
+
LIBRARY = {
|
|
180
|
+
# -------------------------------------------------------------- FDM
|
|
181
|
+
"pla": _c("PLA (values from Prusament PLA)", ("fdm",),
|
|
182
|
+
E=(2300, "prusament-pla", "tensile modulus, horizontal"),
|
|
183
|
+
nu=_NU_POLY,
|
|
184
|
+
strength=(51, "prusament-pla", "tensile yield strength, horizontal"),
|
|
185
|
+
strengthZ=(17, "prusament-pla", "interlayer adhesion"),
|
|
186
|
+
density=(1.24, "prusament-pla", "ISO 1183"),
|
|
187
|
+
elongation=(2.9, "prusament-pla", "% at yield, horizontal"),
|
|
188
|
+
hdt=(55, "prusament-pla", "ISO 75, 0.45 MPa"),
|
|
189
|
+
hdt18=(55, "prusament-pla", "ISO 75, 1.80 MPa"),
|
|
190
|
+
conductivity=(0.19, "tychanicz-2025", "W/(m K)"),
|
|
191
|
+
specificHeat=(1800, "polymer-handbook", "J/(kg K) near 25 C; amorphous PLA 1.2-1.8 kJ/(kg K), DSC"),
|
|
192
|
+
fatigue=("pla", "durability", "Ezeh & Susmel design curve"),
|
|
193
|
+
cte=(68, "estimate", "um/(m K) near 23 C; typical printed PLA, in plane"),
|
|
194
|
+
retention=([(23, 1.0), (45, 0.92), (55, 0.6), (60, 0.2), (65, 0.04)], "dma-estimate", _RET)),
|
|
195
|
+
"petg": _c("PETG (values from Prusament PETG)", ("fdm",),
|
|
196
|
+
E=(1500, "prusament-petg", "tensile modulus, horizontal"),
|
|
197
|
+
nu=(0.38, "estimate", "copolyester; datasheets don't list it"),
|
|
198
|
+
strength=(47, "prusament-petg", "tensile yield strength, horizontal"),
|
|
199
|
+
strengthZ=(18, "prusament-petg", "interlayer adhesion"),
|
|
200
|
+
density=(1.27, "prusament-petg", "ISO 1183"),
|
|
201
|
+
elongation=(5.1, "prusament-petg", "% at yield, horizontal"),
|
|
202
|
+
hdt=(68, "prusament-petg", "ISO 75, 0.45 MPa"),
|
|
203
|
+
hdt18=(68, "prusament-petg", "ISO 75, 1.80 MPa"),
|
|
204
|
+
conductivity=(0.20, "tychanicz-2025", "W/(m K)"),
|
|
205
|
+
specificHeat=(1200, "polymer-handbook", "J/(kg K) near 25 C; PET copolyesters 1.1-1.3"),
|
|
206
|
+
fatigue=("petg", "durability", "PLA curve scaled by strength (assumed)"),
|
|
207
|
+
cte=(68, "estimate", "um/(m K) near 23 C; typical copolyester"),
|
|
208
|
+
retention=([(23, 1.0), (40, 0.93), (55, 0.8), (65, 0.6), (75, 0.25), (85, 0.05)], "dma-estimate", _RET)),
|
|
209
|
+
"abs": _c("ABS (values from Polymaker PolyLite ABS)", ("fdm",),
|
|
210
|
+
E=(2174, "polylite-abs", "Young's modulus X-Y"),
|
|
211
|
+
EZ=(1835, "polylite-abs", "Young's modulus Z"),
|
|
212
|
+
nu=(0.35, "estimate", "datasheets don't list it"),
|
|
213
|
+
strength=(33.3, "polylite-abs", "tensile strength X-Y"),
|
|
214
|
+
strengthZ=(25.4, "polylite-abs", "tensile strength Z"),
|
|
215
|
+
density=(1.12, "polylite-abs", "ISO 1183"),
|
|
216
|
+
elongation=(2.7, "polylite-abs", "% at break, X-Y"),
|
|
217
|
+
tg=(101.1, "polylite-abs", "DSC"),
|
|
218
|
+
hdt=(99.6, "polylite-abs", "ISO 75, 0.45 MPa"),
|
|
219
|
+
hdt18=(98.2, "polylite-abs", "ISO 75, 1.8 MPa"),
|
|
220
|
+
conductivity=(0.17, "estimate", "W/(m K), bulk ABS"),
|
|
221
|
+
specificHeat=(1400, "polymer-handbook", "J/(kg K) near 25 C; ABS 1.3-1.7"),
|
|
222
|
+
fatigue=("abs", "durability", "PLA curve scaled by strength (assumed)"),
|
|
223
|
+
cte=(90, "estimate", "um/(m K) near 23 C; typical ABS"),
|
|
224
|
+
retention=([(23, 1.0), (60, 0.85), (80, 0.65), (95, 0.25), (105, 0.04)], "dma-estimate", _RET)),
|
|
225
|
+
"asa": _c("ASA (values from Polymaker PolyLite ASA)", ("fdm",),
|
|
226
|
+
E=(2379, "polylite-asa", "Young's modulus X-Y"),
|
|
227
|
+
EZ=(1965, "polylite-asa", "Young's modulus Z"),
|
|
228
|
+
nu=(0.35, "estimate", "datasheets don't list it"),
|
|
229
|
+
strength=(43.8, "polylite-asa", "tensile strength X-Y"),
|
|
230
|
+
strengthZ=(32.0, "polylite-asa", "tensile strength Z"),
|
|
231
|
+
density=(1.13, "polylite-asa", "ISO 1183"),
|
|
232
|
+
elongation=(6.7, "polylite-asa", "% at break, X-Y"),
|
|
233
|
+
tg=(97.8, "polylite-asa", "DSC"),
|
|
234
|
+
hdt=(102.6, "polylite-asa", "ISO 75, 0.45 MPa"),
|
|
235
|
+
hdt18=(100.2, "polylite-asa", "ISO 75, 1.8 MPa"),
|
|
236
|
+
conductivity=(0.17, "estimate", "W/(m K), as ABS"),
|
|
237
|
+
specificHeat=(1300, "estimate", "J/(kg K), close to ABS"),
|
|
238
|
+
fatigue=("asa", "durability", "PLA curve scaled by strength (assumed)"),
|
|
239
|
+
cte=(95, "estimate", "um/(m K) near 23 C; typical ASA"),
|
|
240
|
+
retention=([(23, 1.0), (60, 0.85), (80, 0.65), (95, 0.25), (105, 0.04)], "dma-estimate", _RET)),
|
|
241
|
+
# 95A: linear analysis holds only to a few percent strain; flexures
|
|
242
|
+
# want verify_nonlinear (nonlinear.py)
|
|
243
|
+
"tpu": _c("TPU 95A (values from UltiMaker TPU 95A); small strains only", ("fdm",),
|
|
244
|
+
E=(67, "ultimaker-tpu95a", "tensile modulus XY"),
|
|
245
|
+
EZ=(56, "ultimaker-tpu95a", "tensile modulus Z"),
|
|
246
|
+
nu=(0.45, "estimate", "elastomers are nearly incompressible"),
|
|
247
|
+
strength=(23.7, "ultimaker-tpu95a", "tensile stress at break XY"),
|
|
248
|
+
strengthZ=(6.4, "ultimaker-tpu95a", "tensile stress at break Z"),
|
|
249
|
+
density=(1.21, "estimate", "the TDS gives none; typical TPU 95A filament 1.20-1.22"),
|
|
250
|
+
elongation=(560, "ultimaker-tpu95a", "% at break XY (> 560)"),
|
|
251
|
+
hdt=(50.3, "ultimaker-tpu95a", "ISO 75-2/B, 0.455 MPa"),
|
|
252
|
+
conductivity=(0.20, "estimate", "W/(m K)"),
|
|
253
|
+
specificHeat=(1700, "estimate", "J/(kg K), polyether TPUs 1.5-1.9"),
|
|
254
|
+
fatigue=("tpu", "durability", "rough estimate"),
|
|
255
|
+
cte=(150, "estimate", "um/(m K) near 23 C; typical TPU 95A"),
|
|
256
|
+
retention=([(23, 1.0), (40, 0.85), (60, 0.7), (80, 0.55), (100, 0.4)], "dma-estimate", _RET)),
|
|
257
|
+
"pa-cf": _c("carbon-filled nylon (values from Bambu PAHT-CF, dry)", ("fdm",),
|
|
258
|
+
E=(3860, "bambu-paht-cf", "Young's modulus X-Y, dry"),
|
|
259
|
+
EZ=(2180, "bambu-paht-cf", "Young's modulus Z, dry"),
|
|
260
|
+
nu=(0.35, "estimate", "datasheets don't list it"),
|
|
261
|
+
strength=(92, "bambu-paht-cf", "tensile strength X-Y, dry"),
|
|
262
|
+
strengthZ=(47, "bambu-paht-cf", "tensile strength Z, dry"),
|
|
263
|
+
density=(1.06, "bambu-paht-cf", "ISO 1183"),
|
|
264
|
+
tg=(70, "bambu-paht-cf", "DSC"),
|
|
265
|
+
hdt=(194, "bambu-paht-cf", "ISO 75, 0.45 MPa"),
|
|
266
|
+
hdt18=(170, "bambu-paht-cf", "ISO 75, 1.8 MPa"),
|
|
267
|
+
conductivity=(0.40, "estimate", "W/(m K), fibre-filled, in plane"),
|
|
268
|
+
specificHeat=(1300, "estimate", "J/(kg K); PA6 ~1.6 lowered for ~15% carbon fibre"),
|
|
269
|
+
fatigue=("pa-cf", "durability", "rough estimate"),
|
|
270
|
+
cte=(30, "estimate", "um/(m K) along the laid fibres; across them several times more"),
|
|
271
|
+
retention=([(23, 1.0), (50, 0.8), (80, 0.55), (120, 0.35), (150, 0.2)], "dma-estimate", _RET)),
|
|
272
|
+
"pp": _c("polypropylene, printed (generic values; no single datasheet)", ("fdm",),
|
|
273
|
+
E=(1100, "estimate", "printed isotactic PP homopolymer, 0.9-1.3 GPa; copolymer filaments far lower"),
|
|
274
|
+
nu=(0.42, "estimate", "typical PP"),
|
|
275
|
+
strength=(25, "estimate", "printed PP, tensile, in plane"),
|
|
276
|
+
strengthZ=(15, "estimate", "interlayer, roughly 0.6 of in-plane"),
|
|
277
|
+
density=(0.90, "estimate", "PP 0.90-0.91"),
|
|
278
|
+
conductivity=(0.20, "estimate", "W/(m K), PP"),
|
|
279
|
+
specificHeat=(1900, "polymer-handbook", "J/(kg K) near 25 C; PP 1.7-2.0"),
|
|
280
|
+
fatigue=("pp", "durability", "rough estimate"),
|
|
281
|
+
cte=(120, "estimate", "um/(m K) near 23 C; PP 100-150"),
|
|
282
|
+
retention=([(23, 1.0), (60, 0.6), (90, 0.35), (120, 0.15), (150, 0.03)], "dma-estimate", _RET)),
|
|
283
|
+
# ------------------------------------------------------- powder bed
|
|
284
|
+
"pa12": _c("PA 12 (values from HP 3D HR PA 12, MJF)", ("sls", "mjf", "fdm"), "mjf",
|
|
285
|
+
E=(1900, "hp-5200-whitepaper", "tensile modulus XY (95% of parts 1650-2200)"),
|
|
286
|
+
EZ=(1900, "hp-5200-whitepaper", "tensile modulus Z"),
|
|
287
|
+
nu=(0.39, "estimate", "nylon 12; datasheets don't list it"),
|
|
288
|
+
strength=(50, "hp-5200-whitepaper", "tensile strength XY (95% of parts 45-55)"),
|
|
289
|
+
strengthZ=(50, "hp-5200-whitepaper", "tensile strength Z"),
|
|
290
|
+
density=(1.01, "hp-5200-whitepaper", "ASTM D792"),
|
|
291
|
+
elongation=(17, "hp-5200-whitepaper", "% at break XY (Z: 9)"),
|
|
292
|
+
conductivity=(0.25, "estimate", "W/(m K), sintered PA12"),
|
|
293
|
+
specificHeat=(1650, "polymer-handbook", "J/(kg K) near 25 C; PA12 1.6-1.7"),
|
|
294
|
+
fatigue=("pa12", "durability", "Van Hooreweder & Kruth 2014"),
|
|
295
|
+
cte=(109, "estimate", "um/(m K) near 23 C; typical sintered PA12"),
|
|
296
|
+
retention=([(23, 1.0), (45, 0.75), (80, 0.45), (120, 0.25), (160, 0.1)], "dma-estimate", _RET)),
|
|
297
|
+
"pa11": _c("PA 11 (values from HP 3D HR PA 11, MJF): tougher than PA12", ("sls", "mjf"), "mjf",
|
|
298
|
+
E=(1700, "hp-5200-whitepaper", "tensile modulus XY"),
|
|
299
|
+
EZ=(1800, "hp-5200-whitepaper", "tensile modulus Z"),
|
|
300
|
+
nu=(0.39, "estimate", "as PA12"),
|
|
301
|
+
strength=(54, "hp-5200-whitepaper", "tensile strength XY"),
|
|
302
|
+
strengthZ=(54, "hp-5200-whitepaper", "tensile strength Z"),
|
|
303
|
+
density=(1.05, "hp-5200-whitepaper", "ASTM D792"),
|
|
304
|
+
elongation=(40, "hp-5200-whitepaper", "% at break XY (Z: 25)"),
|
|
305
|
+
conductivity=(0.25, "estimate", "W/(m K), as PA12"),
|
|
306
|
+
specificHeat=(1600, "estimate", "J/(kg K), as PA12"),
|
|
307
|
+
fatigue=("pa11", "durability", "as PA12 (assumed)"),
|
|
308
|
+
cte=(100, "estimate", "um/(m K) near 23 C; typical PA11"),
|
|
309
|
+
retention=([(23, 1.0), (45, 0.75), (80, 0.45), (120, 0.25), (160, 0.1)], "dma-estimate", _RET)),
|
|
310
|
+
"pa12-gb": _c("glass-bead PA 12 (values from HP 3D HR PA 12 GB): stiff, stable, brittle", ("sls", "mjf"), "mjf",
|
|
311
|
+
E=(2900, "hp-5200-whitepaper", "tensile modulus XY"),
|
|
312
|
+
EZ=(3000, "hp-5200-whitepaper", "tensile modulus Z"),
|
|
313
|
+
nu=(0.37, "estimate", "filled nylon"),
|
|
314
|
+
strength=(31, "hp-5200-whitepaper", "tensile strength XY"),
|
|
315
|
+
strengthZ=(30, "hp-5200-whitepaper", "tensile strength Z"),
|
|
316
|
+
density=(1.30, "hp-5200-whitepaper", "ASTM D792"),
|
|
317
|
+
elongation=(9, "hp-5200-whitepaper", "% at break XY"),
|
|
318
|
+
hdt=(170, "hp-5200-whitepaper", "ASTM D648, 0.45 MPa, XY"),
|
|
319
|
+
hdt18=(113, "hp-5200-whitepaper", "ASTM D648, 1.82 MPa, XY")),
|
|
320
|
+
"pa12-gf": _c("glass-filled PA 12 (values from EOS PA 3200 GF, SLS): stiff, wear resistant", ("sls",),
|
|
321
|
+
E=(3200, "eos-pa3200gf", "tensile modulus X"),
|
|
322
|
+
EZ=(2500, "eos-pa3200gf", "tensile modulus Z"),
|
|
323
|
+
nu=(0.37, "estimate", "filled nylon"),
|
|
324
|
+
strength=(51, "eos-pa3200gf", "tensile strength X"),
|
|
325
|
+
strengthZ=(47, "eos-pa3200gf", "tensile strength Z"),
|
|
326
|
+
density=(1.22, "eos-pa3200gf", "laser-sintered part density (EOS method)"),
|
|
327
|
+
elongation=(9, "eos-pa3200gf", "% at break X (Z: 5.5)"),
|
|
328
|
+
hdt=(157, "eos-pa3200gf", "ISO 75, 0.45 MPa, X"),
|
|
329
|
+
hdt18=(96, "eos-pa3200gf", "ISO 75, 1.80 MPa, X")),
|
|
330
|
+
"tpu88a": _c("TPU 88A (values from BASF Ultrasint TPU 88A, SLS): a linear analysis is a rough estimate "
|
|
331
|
+
"past a few percent strain; run verify_nonlinear", ("sls", "mjf"),
|
|
332
|
+
E=(75, "basf-tpu88a", "tensile modulus X (ISO 527-2 1A)"),
|
|
333
|
+
EZ=(75, "basf-tpu88a", "tensile modulus Z"),
|
|
334
|
+
nu=(0.45, "estimate", "elastomers are nearly incompressible"),
|
|
335
|
+
strength=(8, "basf-tpu88a", "tensile strength X (DIN 53504 S2)"),
|
|
336
|
+
strengthZ=(7, "basf-tpu88a", "tensile strength Z"),
|
|
337
|
+
density=(1.10, "basf-tpu88a", "printed part, ISO 1183-1"),
|
|
338
|
+
elongation=(270, "basf-tpu88a", "% at break X (Z: 130)")),
|
|
339
|
+
# ------------------------------------------------------------ resin
|
|
340
|
+
"resin": _c("standard resin (values from Formlabs Grey V4, post-cured)", ("sla", "dlp"),
|
|
341
|
+
E=(2800, "formlabs-standard", "tensile modulus, post-cured"),
|
|
342
|
+
nu=(0.38, "estimate", "acrylate photopolymer"),
|
|
343
|
+
strength=(65, "formlabs-standard", "ultimate tensile strength, post-cured"),
|
|
344
|
+
density=(1.18, "estimate", "the TDS gives none; cured acrylates 1.15-1.20"),
|
|
345
|
+
elongation=(6, "formlabs-standard", "% at break, post-cured"),
|
|
346
|
+
hdt=(73, "formlabs-standard", "ASTM D648, 0.45 MPa"),
|
|
347
|
+
hdt18=(58, "formlabs-standard", "ASTM D648, 1.8 MPa"),
|
|
348
|
+
conductivity=(0.18, "estimate", "W/(m K)"),
|
|
349
|
+
specificHeat=(1400, "estimate", "J/(kg K), cured acrylates 1.2-1.6"),
|
|
350
|
+
fatigue=("resin", "durability", "rough estimate"),
|
|
351
|
+
cte=(79, "formlabs-standard", "um/(m K), 0-150 C, post-cured (ASTM E831)"),
|
|
352
|
+
retention=([(23, 1.0), (40, 0.8), (50, 0.5), (60, 0.2), (70, 0.05)], "dma-estimate", _RET)),
|
|
353
|
+
"resin-tough": _c("tough resin (values from Formlabs Tough 2000, post-cured)", ("sla", "dlp"),
|
|
354
|
+
E=(2200, "formlabs-tough2000", "tensile modulus, post-cured"),
|
|
355
|
+
nu=(0.40, "estimate", "toughened photopolymer"),
|
|
356
|
+
strength=(46, "formlabs-tough2000", "ultimate tensile strength, post-cured"),
|
|
357
|
+
density=(1.15, "estimate", "the TDS gives none"),
|
|
358
|
+
elongation=(48, "formlabs-tough2000", "% at break, post-cured"),
|
|
359
|
+
hdt=(63, "formlabs-tough2000", "ASTM D648, 0.45 MPa"),
|
|
360
|
+
hdt18=(53, "formlabs-tough2000", "ASTM D648, 1.8 MPa"),
|
|
361
|
+
cte=(91, "formlabs-tough2000", "um/(m K), 0-150 C, post-cured (ASTM E831)"),
|
|
362
|
+
conductivity=(0.18, "estimate", "W/(m K)"),
|
|
363
|
+
specificHeat=(1400, "estimate", "J/(kg K), cured acrylates 1.2-1.6"),
|
|
364
|
+
fatigue=("resin-tough", "durability", "rough estimate"),
|
|
365
|
+
retention=([(23, 1.0), (40, 0.75), (50, 0.45), (60, 0.2), (70, 0.05)], "dma-estimate", _RET)),
|
|
366
|
+
"resin-rigid": _c("glass-filled rigid resin (values from Formlabs Rigid 10K, UV cure): brittle", ("sla", "dlp"),
|
|
367
|
+
E=(10000, "formlabs-rigid10k", "tensile modulus, UV post-cure"),
|
|
368
|
+
nu=(0.33, "estimate", "highly glass-filled photopolymer"),
|
|
369
|
+
strength=(65, "formlabs-rigid10k", "ultimate tensile strength, UV post-cure"),
|
|
370
|
+
density=(1.65, "estimate", "the TDS gives none; glass-filled acrylates 1.6-1.7"),
|
|
371
|
+
elongation=(1, "formlabs-rigid10k", "% at break, UV post-cure"),
|
|
372
|
+
cte=(47, "formlabs-rigid10k", "um/(m K), 0-150 C, UV post-cure (ASTM E831)")),
|
|
373
|
+
# ---------------------------------------------------------- jetting
|
|
374
|
+
# PolyJet (material jetting): rigid and rubber-like photopolymers jetted
|
|
375
|
+
# and UV-cured in the same layers; interface_library.py has their bond.
|
|
376
|
+
# The datasheets give ranges; the cards take the low end.
|
|
377
|
+
"vero": _c("rigid PolyJet photopolymer (values from Stratasys Vero / Rigid Opaque, low end of the "
|
|
378
|
+
"family's ranges)", ("jetting",),
|
|
379
|
+
E=(2000, "stratasys-vero", "modulus of elasticity, ASTM D638 (range 2000-3000)"),
|
|
380
|
+
nu=(0.38, "estimate", "acrylate photopolymer, as resin"),
|
|
381
|
+
strength=(50, "stratasys-vero", "tensile strength, ASTM D638 (range 50-65)"),
|
|
382
|
+
density=(1.17, "stratasys-vero", "polymerized density (range 1.17-1.18)"),
|
|
383
|
+
elongation=(10, "stratasys-vero", "% at break, ASTM D638 (range 10-25)"),
|
|
384
|
+
tg=(52, "stratasys-vero", "DMA (range 52-54)"),
|
|
385
|
+
hdt=(45, "stratasys-vero", "ASTM D648, 0.45 MPa (range 45-50)"),
|
|
386
|
+
hdt18=(45, "stratasys-vero", "ASTM D648, 1.82 MPa (range 45-50)"),
|
|
387
|
+
conductivity=(0.18, "estimate", "W/(m K), as other cured acrylates")),
|
|
388
|
+
"agilus30": _c("rubber-like PolyJet photopolymer, Shore 30A (values from Stratasys Agilus30): a linear "
|
|
389
|
+
"analysis is a rough estimate past a few percent strain; run verify_nonlinear", ("jetting",),
|
|
390
|
+
E=(1.1, "estimate", "the TDS gives none; Gent's Shore A relation at 30A gives ~1.1 MPa "
|
|
391
|
+
"(initial tangent modulus)"),
|
|
392
|
+
nu=(0.45, "estimate", "elastomers are nearly incompressible; 0.45 keeps the linear solve "
|
|
393
|
+
"well conditioned"),
|
|
394
|
+
strength=(2.4, "stratasys-agilus30", "tensile strength, ASTM D412, Black/Translucent "
|
|
395
|
+
"(range 2.4-3.1; White 2.1-2.6)"),
|
|
396
|
+
density=(1.14, "stratasys-agilus30", "polymerized density, ASTM D792 (range 1.14-1.15)"),
|
|
397
|
+
elongation=(220, "stratasys-agilus30", "% at break, ASTM D412, Black/Translucent "
|
|
398
|
+
"(range 220-270; White 185-230)"),
|
|
399
|
+
hardness=(30, "stratasys-agilus30", "Shore A, ASTM D2240 (range 30-35)")),
|
|
400
|
+
# ------------------------------------------------------------- LPBF
|
|
401
|
+
"alsi10mg": _c("LPBF AlSi10Mg, as built (values from AddUp)", ("lpbf",),
|
|
402
|
+
E=(72000, "addup-alsi10mg", "modulus XY, as built (Z 71 GPa)"),
|
|
403
|
+
EZ=(71000, "addup-alsi10mg", "modulus Z, as built"),
|
|
404
|
+
nu=(0.33, "handbook", "aluminium alloys"),
|
|
405
|
+
strength=(275, "addup-alsi10mg", "yield strength XY, as built"),
|
|
406
|
+
strengthZ=(239, "addup-alsi10mg", "yield strength Z, as built"),
|
|
407
|
+
density=(2.67, "addup-alsi10mg", "theoretical; parts 99.5% dense"),
|
|
408
|
+
elongation=(5, "addup-alsi10mg", "% at failure, XY and Z"),
|
|
409
|
+
conductivity=(125, "addup-alsi10mg", "W/(m K), low end of the sheet's 120-160 at 25 C"),
|
|
410
|
+
specificHeat=(900, "handbook", "J/(kg K) near 25 C; Al-Si casting alloys 880-920"),
|
|
411
|
+
fatigue=("alsi10mg", "durability", "rough, as-built surface"),
|
|
412
|
+
cte=(21, "addup-alsi10mg", "um/(m K), 20-100 C"),
|
|
413
|
+
retention=([(23, 1.0), (150, 0.92), (200, 0.85), (300, 0.6)], "dma-estimate", _RET)),
|
|
414
|
+
"ti64": _c("LPBF Ti-6Al-4V, heat treated (values from EOS)", ("lpbf",),
|
|
415
|
+
E=(110000, "eos-ti64", "modulus XY and Z, +-15 GPa"),
|
|
416
|
+
EZ=(110000, "eos-ti64", "modulus Z"),
|
|
417
|
+
nu=(0.34, "handbook", "Ti-6Al-4V"),
|
|
418
|
+
strength=(1000, "eos-ti64", "yield strength Rp0.2 XY, heat treated (min 860)"),
|
|
419
|
+
strengthZ=(1000, "eos-ti64", "yield strength Rp0.2 Z, heat treated"),
|
|
420
|
+
density=(4.41, "eos-ti64", "part density"),
|
|
421
|
+
elongation=(13.5, "eos-ti64", "% at break, heat treated"),
|
|
422
|
+
conductivity=(6.7, "handbook", "W/(m K), Ti-6Al-4V"),
|
|
423
|
+
specificHeat=(526, "handbook", "J/(kg K), Ti-6Al-4V at 25 C"),
|
|
424
|
+
fatigueStrength=(595, "eos-ti64-grade5", "MPa at 1e7 cycles, heat treated (Grade 5 sheet)"),
|
|
425
|
+
fatigue=("ti64", "durability", "rough, as-built surface"),
|
|
426
|
+
cte=(8.6, "handbook", "um/(m K), 20-100 C, Ti-6Al-4V"),
|
|
427
|
+
retention=([(23, 1.0), (300, 0.85), (500, 0.75)], "dma-estimate", _RET)),
|
|
428
|
+
"316l": _c("LPBF 316L stainless, as built (values from AddUp)", ("lpbf",),
|
|
429
|
+
E=(193000, "addup-316l", "modulus XY, as built"),
|
|
430
|
+
EZ=(160000, "addup-316l", "modulus Z, as built"),
|
|
431
|
+
nu=(0.30, "handbook", "austenitic stainless"),
|
|
432
|
+
strength=(699, "addup-316l", "yield strength XY, as built"),
|
|
433
|
+
strengthZ=(632, "addup-316l", "yield strength Z, as built"),
|
|
434
|
+
density=(8.0, "addup-316l", "theoretical; parts 99.9% dense"),
|
|
435
|
+
conductivity=(15, "addup-316l", "W/(m K) at 20 C"),
|
|
436
|
+
specificHeat=(500, "handbook", "J/(kg K), 316L at 25 C"),
|
|
437
|
+
fatigue=("316l", "durability", "rough, as-built surface"),
|
|
438
|
+
cte=(17.2, "addup-316l", "um/(m K), RT-200 C (the sheet's literature value)"),
|
|
439
|
+
retention=([(23, 1.0), (300, 0.9), (500, 0.82)], "dma-estimate", _RET)),
|
|
440
|
+
"in625": _c("LPBF Inconel 625, as built (values from EOS)", ("lpbf",),
|
|
441
|
+
E=(204000, "eos-in625", "modulus Z, heat treated (as built reads 10-20% lower on other sheets)"),
|
|
442
|
+
nu=(0.31, "handbook", "nickel alloy 625"),
|
|
443
|
+
strength=(720, "eos-in625", "yield strength Rp0.2 XY, as built"),
|
|
444
|
+
strengthZ=(630, "eos-in625", "yield strength Rp0.2 Z, as built"),
|
|
445
|
+
density=(8.44, "handbook", "alloy 625"),
|
|
446
|
+
conductivity=(9.8, "handbook", "W/(m K) at 20 C, alloy 625"),
|
|
447
|
+
cte=(12.8, "handbook", "um/(m K), 20-100 C, alloy 625"),
|
|
448
|
+
retention=([(23, 1.0), (300, 0.93), (500, 0.88)], "dma-estimate", _RET)),
|
|
449
|
+
"15-5ph": _c("LPBF 15-5 PH stainless, as built (values from EOS PH1)", ("lpbf",),
|
|
450
|
+
E=(196000, "handbook", "wrought 15-5 PH; the EOS sheet gives none"),
|
|
451
|
+
nu=(0.27, "handbook", "precipitation-hardening stainless"),
|
|
452
|
+
strength=(1025, "eos-ph1", "yield strength Rp0.2 XY, as built"),
|
|
453
|
+
strengthZ=(930, "eos-ph1", "yield strength Rp0.2 Z, as built"),
|
|
454
|
+
density=(7.8, "handbook", "15-5 PH"),
|
|
455
|
+
conductivity=(17.8, "handbook", "W/(m K) at 100 C, 15-5 PH"),
|
|
456
|
+
cte=(10.8, "handbook", "um/(m K), 20-100 C, 15-5 PH"),
|
|
457
|
+
retention=([(23, 1.0), (300, 0.9), (500, 0.8)], "dma-estimate", _RET)),
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
def card_names():
|
|
462
|
+
return sorted(LIBRARY)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
def card(name):
|
|
466
|
+
"""The library card (dict) for a material name, or None."""
|
|
467
|
+
return LIBRARY.get(str(name).strip().lower())
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
def value(name, key, default=None):
|
|
471
|
+
"""A card's number for `key` (e.g. "strengthZ"), or default."""
|
|
472
|
+
c = card(name)
|
|
473
|
+
if c is None or key not in c["values"]:
|
|
474
|
+
return default
|
|
475
|
+
return c["values"][key][0]
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
def describe(name):
|
|
479
|
+
"""A card as JSON: every value with its source's title and url."""
|
|
480
|
+
c = card(name)
|
|
481
|
+
if c is None:
|
|
482
|
+
return None
|
|
483
|
+
vals = {}
|
|
484
|
+
for k, (v, src, note) in c["values"].items():
|
|
485
|
+
s = SOURCES[src]
|
|
486
|
+
vals[k] = {"value": v, "note": note, "source": s.title, **({"url": s.url} if s.url else {})}
|
|
487
|
+
return {"name": str(name).strip().lower(), "title": c["title"], "processes": list(c["processes"]),
|
|
488
|
+
"measured": c["measured"],
|
|
489
|
+
"values": vals, "accessed": ACCESSED}
|
loadpath/materials.py
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Material properties for the verification pass.
|
|
3
|
+
|
|
4
|
+
The optimizer itself does not need any of this: for a linear elastic
|
|
5
|
+
compliance problem the optimal layout is independent of Young's modulus, so
|
|
6
|
+
the solver runs on E = 1. Material only enters when we turn an outcome into
|
|
7
|
+
numbers a person acts on (stress against strength, deflection in mm, mass in
|
|
8
|
+
grams).
|
|
9
|
+
|
|
10
|
+
Values come from named datasheets of printed parts, each value cited in
|
|
11
|
+
material_library.py (`loadpath materials` lists them); they are typical
|
|
12
|
+
values, not certified allowables. Printed plastics are anisotropic (weaker across layers, often by
|
|
13
|
+
half for FDM) and the analysis is linear, so a safety factor computed from
|
|
14
|
+
these is an estimate to compare designs and to catch an undersized part, not
|
|
15
|
+
a sign-off.
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
|
|
21
|
+
from .material_library import LIBRARY
|
|
22
|
+
|
|
23
|
+
__all__ = ["Material", "MATERIALS", "material_from_spec"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class Material:
|
|
28
|
+
name: str
|
|
29
|
+
E: float # Young's modulus, MPa
|
|
30
|
+
nu: float # Poisson's ratio
|
|
31
|
+
strength: float # MPa: yield for metals, tensile strength for polymers
|
|
32
|
+
density: float # g/cm^3
|
|
33
|
+
note: str = ""
|
|
34
|
+
# the processes (spec.PROCESSES) it is printed by; empty = any
|
|
35
|
+
processes: tuple = ()
|
|
36
|
+
# across layers, when the datasheet measured it (MPa); None = in-plane
|
|
37
|
+
# values with the process's own factors (spec.PROCESSES)
|
|
38
|
+
E_z: float | None = None
|
|
39
|
+
strength_z: float | None = None
|
|
40
|
+
# the process the datasheet's specimens were made by: E_z and
|
|
41
|
+
# strength_z apply to a study printed that way
|
|
42
|
+
measured: str = ""
|
|
43
|
+
|
|
44
|
+
def to_dict(self):
|
|
45
|
+
out = {"name": self.name, "E": self.E, "nu": self.nu,
|
|
46
|
+
"strength": self.strength, "density": self.density, "note": self.note,
|
|
47
|
+
"processes": list(self.processes)}
|
|
48
|
+
if self.E_z is not None:
|
|
49
|
+
out["EZ"] = self.E_z
|
|
50
|
+
if self.strength_z is not None:
|
|
51
|
+
out["strengthZ"] = self.strength_z
|
|
52
|
+
if self.measured:
|
|
53
|
+
out["measured"] = self.measured
|
|
54
|
+
return out
|
|
55
|
+
|
|
56
|
+
def across_layers(self):
|
|
57
|
+
"""(strength ratio, modulus ratio) across layers from the datasheet,
|
|
58
|
+
each capped at 1, or None where it wasn't measured."""
|
|
59
|
+
s = min(1.0, self.strength_z / self.strength) if self.strength_z else None
|
|
60
|
+
e = min(1.0, self.E_z / self.E) if self.E_z else None
|
|
61
|
+
return s, e
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _from_card(name, c):
|
|
65
|
+
v = c["values"]
|
|
66
|
+
get = (lambda k: float(v[k][0]) if k in v else None)
|
|
67
|
+
return Material(name, get("E"), get("nu"), get("strength"), get("density"), c["title"],
|
|
68
|
+
c["processes"], E_z=get("EZ"), strength_z=get("strengthZ"),
|
|
69
|
+
measured=c.get("measured", c["processes"][0]))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# every value sourced: material_library.py (`loadpath materials <name>`)
|
|
73
|
+
MATERIALS = {k: _from_card(k, c) for k, c in LIBRARY.items()}
|
|
74
|
+
|
|
75
|
+
_ALIASES = {
|
|
76
|
+
"nylon": "pa12", "pa": "pa12", "pa 12": "pa12", "pa-12": "pa12",
|
|
77
|
+
"aluminium": "alsi10mg", "aluminum": "alsi10mg", "titanium": "ti64",
|
|
78
|
+
"stainless": "316l", "steel": "316l", "carbon nylon": "pa-cf",
|
|
79
|
+
"tpu95a": "tpu", "tpu 95a": "tpu", "flex": "tpu",
|
|
80
|
+
"pa 11": "pa11", "pa-11": "pa11", "pa12gb": "pa12-gb", "glass nylon": "pa12-gb",
|
|
81
|
+
"pa12gf": "pa12-gf", "pa 3200 gf": "pa12-gf", "pa3200gf": "pa12-gf",
|
|
82
|
+
"tpu 88a": "tpu88a", "tpu-88a": "tpu88a", "sla": "resin", "standard resin": "resin", "tough resin": "resin-tough",
|
|
83
|
+
"rigid resin": "resin-rigid",
|
|
84
|
+
"verowhite": "vero", "vero white": "vero", "agilus": "agilus30", "agilus 30": "agilus30",
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def material_from_spec(spec) -> Material:
|
|
89
|
+
"""A name from MATERIALS (or an alias), a calibrated card's name, or a
|
|
90
|
+
custom {"name"?, "E", "nu", "strength", "density"} object; a custom
|
|
91
|
+
object with "base": <name> starts from that material and changes only
|
|
92
|
+
the keys it gives. A calibrated card (calibration.py, measured on your
|
|
93
|
+
printer) named like a library material replaces it."""
|
|
94
|
+
if isinstance(spec, Material):
|
|
95
|
+
return spec
|
|
96
|
+
if isinstance(spec, str):
|
|
97
|
+
key = spec.strip().lower()
|
|
98
|
+
from .calibration import list_cards, load_card
|
|
99
|
+
cal = _calibrated(key, load_card)
|
|
100
|
+
if cal is not None:
|
|
101
|
+
return cal
|
|
102
|
+
key = _ALIASES.get(key, key)
|
|
103
|
+
if key in MATERIALS:
|
|
104
|
+
return MATERIALS[key]
|
|
105
|
+
raise ValueError(f"unknown material {spec!r}; known: {sorted(MATERIALS)}"
|
|
106
|
+
+ (f", calibrated: {list_cards()}" if list_cards() else "")
|
|
107
|
+
+ " or pass {E, nu, strength, density}")
|
|
108
|
+
if isinstance(spec, dict):
|
|
109
|
+
base = material_from_spec(spec["base"]) if spec.get("base") is not None else None
|
|
110
|
+
d = dict(base.to_dict()) if base is not None else {}
|
|
111
|
+
d.update({k: v for k, v in spec.items() if k != "base"})
|
|
112
|
+
if base is not None and "name" not in spec:
|
|
113
|
+
d["name"] = f"{base.name}-custom"
|
|
114
|
+
if base is not None and "note" not in spec:
|
|
115
|
+
d["note"] = f"{base.name} with {', '.join(sorted(k for k in spec if k not in ('base', 'name')))} changed"
|
|
116
|
+
try:
|
|
117
|
+
m = Material(str(d.get("name", "custom")), float(d["E"]), float(d.get("nu", 0.35)),
|
|
118
|
+
float(d["strength"]), float(d["density"]), str(d.get("note", "")),
|
|
119
|
+
tuple(d.get("processes") or ()),
|
|
120
|
+
E_z=float(d["EZ"]) if d.get("EZ") is not None else None,
|
|
121
|
+
strength_z=float(d["strengthZ"]) if d.get("strengthZ") is not None else None,
|
|
122
|
+
measured=str(d.get("measured") or ""))
|
|
123
|
+
except KeyError as exc:
|
|
124
|
+
raise ValueError(f"custom material is missing {exc.args[0]!r} (needs E, strength, density, "
|
|
125
|
+
"or a base material)") from None
|
|
126
|
+
if m.E <= 0 or m.strength <= 0 or m.density <= 0 or not (0 <= m.nu < 0.5):
|
|
127
|
+
raise ValueError("custom material needs E, strength, density > 0 and 0 <= nu < 0.5")
|
|
128
|
+
if (m.E_z is not None and m.E_z <= 0) or (m.strength_z is not None and m.strength_z <= 0):
|
|
129
|
+
raise ValueError("custom material EZ and strengthZ must be > 0")
|
|
130
|
+
return m
|
|
131
|
+
raise ValueError("material must be a name or {E, nu, strength, density}")
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _calibrated(key, load_card):
|
|
135
|
+
"""The Material of a calibrated card named `key`, or None. Its
|
|
136
|
+
across-layer factors travel in the card's process block (spec.py)."""
|
|
137
|
+
card = load_card(key)
|
|
138
|
+
if card is None:
|
|
139
|
+
return None
|
|
140
|
+
m = card["material"]
|
|
141
|
+
base = MATERIALS.get(_ALIASES.get(card.get("basedOn", ""), card.get("basedOn", "")))
|
|
142
|
+
return Material(card["name"], float(m["E"]), float(m["nu"]), float(m["strength"]),
|
|
143
|
+
float(m["density"]), str(m.get("note", "")),
|
|
144
|
+
tuple(m.get("processes") or (base.processes if base else ())))
|