simcon-toolkit 0.1.0__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.
- simcon_toolkit/__init__.py +40 -0
- simcon_toolkit/__main__.py +7 -0
- simcon_toolkit/_kit/LICENSE +202 -0
- simcon_toolkit/_kit/NOTICE +37 -0
- simcon_toolkit/_kit/assets/parts/clip_frame.stl +0 -0
- simcon_toolkit/_kit/assets/parts/simple_plate.stl +0 -0
- simcon_toolkit/_kit/packages/.ruff.toml +10 -0
- simcon_toolkit/_kit/packages/cadmould_cloud/__init__.py +8 -0
- simcon_toolkit/_kit/packages/cadmould_cloud/auth.py +681 -0
- simcon_toolkit/_kit/packages/cadmould_cloud/client.py +235 -0
- simcon_toolkit/_kit/packages/cadmould_geometry/__init__.py +5 -0
- simcon_toolkit/_kit/packages/cadmould_geometry/mesh.py +210 -0
- simcon_toolkit/_kit/packages/cadmould_geometry/stl.py +168 -0
- simcon_toolkit/_kit/packages/cadmould_results/__init__.py +30 -0
- simcon_toolkit/_kit/packages/cadmould_results/loader.py +288 -0
- simcon_toolkit/_kit/packages/cadmould_scoring/__init__.py +7 -0
- simcon_toolkit/_kit/packages/cadmould_scoring/metrics.py +519 -0
- simcon_toolkit/_kit/pyproject.toml +232 -0
- simcon_toolkit/_kit/templates/_shared/AGENTS.base.md +101 -0
- simcon_toolkit/_kit/templates/gate-study/.gitignore +18 -0
- simcon_toolkit/_kit/templates/gate-study/AGENTS.md +46 -0
- simcon_toolkit/_kit/templates/gate-study/GATING_STUDY_PLAYBOOK.md +219 -0
- simcon_toolkit/_kit/templates/gate-study/INITIAL_PROMPT.md +26 -0
- simcon_toolkit/_kit/templates/gate-study/README.md +137 -0
- simcon_toolkit/_kit/templates/gate-study/main.py +344 -0
- simcon_toolkit/_kit/templates/gate-study/pipeline.py +281 -0
- simcon_toolkit/_kit/templates/process-window/.gitignore +20 -0
- simcon_toolkit/_kit/templates/process-window/AGENTS.md +49 -0
- simcon_toolkit/_kit/templates/process-window/METHOD.md +155 -0
- simcon_toolkit/_kit/templates/process-window/README.md +176 -0
- simcon_toolkit/_kit/templates/process-window/configs/simple-plate.yaml +116 -0
- simcon_toolkit/_kit/templates/process-window/doe_spec.schema.md +249 -0
- simcon_toolkit/_kit/templates/process-window/main.py +82 -0
- simcon_toolkit/_kit/templates/process-window/process_window/__init__.py +5 -0
- simcon_toolkit/_kit/templates/process-window/process_window/centre.py +298 -0
- simcon_toolkit/_kit/templates/process-window/process_window/design.py +144 -0
- simcon_toolkit/_kit/templates/process-window/process_window/economics.py +367 -0
- simcon_toolkit/_kit/templates/process-window/process_window/emit.py +591 -0
- simcon_toolkit/_kit/templates/process-window/process_window/guardrails.py +153 -0
- simcon_toolkit/_kit/templates/process-window/process_window/harness.py +360 -0
- simcon_toolkit/_kit/templates/process-window/process_window/identity.py +92 -0
- simcon_toolkit/_kit/templates/process-window/process_window/inspect_part.py +184 -0
- simcon_toolkit/_kit/templates/process-window/process_window/kpis.py +355 -0
- simcon_toolkit/_kit/templates/process-window/process_window/material_card.py +163 -0
- simcon_toolkit/_kit/templates/process-window/process_window/probe_proxy.py +169 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_confirm.py +403 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_epsilon_floor.py +198 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_feedback.py +322 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_refine.py +279 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_screening.py +370 -0
- simcon_toolkit/_kit/templates/process-window/process_window/run_sweep.py +166 -0
- simcon_toolkit/_kit/templates/process-window/process_window/setup_campaign.py +312 -0
- simcon_toolkit/_kit/templates/process-window/process_window/surrogate.py +201 -0
- simcon_toolkit/_kit/templates/process-window/process_window/test_centre.py +169 -0
- simcon_toolkit/_kit/templates/process-window/process_window/test_design.py +113 -0
- simcon_toolkit/_kit/templates/process-window/process_window/test_guardrails.py +157 -0
- simcon_toolkit/_kit/templates/process-window/process_window/test_surrogate.py +127 -0
- simcon_toolkit/_kit/templates/process-window/process_window/units.py +152 -0
- simcon_toolkit/_kit/templates/quoting/.gitignore +24 -0
- simcon_toolkit/_kit/templates/quoting/AGENTS.md +58 -0
- simcon_toolkit/_kit/templates/quoting/INTERVIEW.md +147 -0
- simcon_toolkit/_kit/templates/quoting/METHOD.md +256 -0
- simcon_toolkit/_kit/templates/quoting/PROMPT.md +46 -0
- simcon_toolkit/_kit/templates/quoting/QUOTING_PLAYBOOK.md +245 -0
- simcon_toolkit/_kit/templates/quoting/README.md +158 -0
- simcon_toolkit/_kit/templates/quoting/main.py +484 -0
- simcon_toolkit/_kit/templates/quoting/parts/.gitkeep +0 -0
- simcon_toolkit/_kit/templates/quoting/quoting/__init__.py +11 -0
- simcon_toolkit/_kit/templates/quoting/quoting/costing.py +725 -0
- simcon_toolkit/_kit/templates/quoting/quoting/geometry.py +398 -0
- simcon_toolkit/_kit/templates/quoting/quoting/shop.py +193 -0
- simcon_toolkit/_kit/templates/quoting/quoting/state.py +260 -0
- simcon_toolkit/_kit/templates/quoting/quoting/study.py +577 -0
- simcon_toolkit/_kit/templates/quoting/quoting/toolkit.py +50 -0
- simcon_toolkit/_kit/templates/quoting/shop/README.md +43 -0
- simcon_toolkit/_kit/templates/quoting/shop/commercial.md +86 -0
- simcon_toolkit/_kit/templates/quoting/shop/lessons.md +94 -0
- simcon_toolkit/_kit/templates/quoting/shop/machines.md +68 -0
- simcon_toolkit/_kit/templates/quoting/shop/materials.md +92 -0
- simcon_toolkit/_kit/templates/quoting/shop/shop-profile.md +87 -0
- simcon_toolkit/_kit/templates/quoting/shop/tooling.md +145 -0
- simcon_toolkit/_kit/templates/run-one-simulation/.gitignore +16 -0
- simcon_toolkit/_kit/templates/run-one-simulation/AGENTS.md +41 -0
- simcon_toolkit/_kit/templates/run-one-simulation/README.md +133 -0
- simcon_toolkit/_kit/templates/run-one-simulation/main.py +216 -0
- simcon_toolkit/_kit/templates.toml +83 -0
- simcon_toolkit/choices.py +11 -0
- simcon_toolkit/cli.py +381 -0
- simcon_toolkit/generate.py +590 -0
- simcon_toolkit/instructions.py +152 -0
- simcon_toolkit/manifest.py +86 -0
- simcon_toolkit/project.py +356 -0
- simcon_toolkit/wizard.py +160 -0
- simcon_toolkit-0.1.0.dist-info/METADATA +48 -0
- simcon_toolkit-0.1.0.dist-info/RECORD +97 -0
- simcon_toolkit-0.1.0.dist-info/WHEEL +4 -0
- simcon_toolkit-0.1.0.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Commercial — rates, allowances, margin, terms
|
|
2
|
+
|
|
3
|
+
> Fictional example. Replace with your controlling department's actual figures.
|
|
4
|
+
|
|
5
|
+
## The piece-price build-up
|
|
6
|
+
|
|
7
|
+
We build a piece price in this order, and the quotation should show it in the same order:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
material (shot mass incl. runner share, minus regrind credit, plus scrap allowance)
|
|
11
|
+
+ machine (loaded hourly rate x cycle time / cavities / OEE)
|
|
12
|
+
+ labour (operator share + any manual work)
|
|
13
|
+
+ secondary (packaging, QC, drying)
|
|
14
|
+
= manufacturing cost
|
|
15
|
+
+ overhead (on material + labour only — the machine rate already carries it)
|
|
16
|
+
+ margin
|
|
17
|
+
= piece price
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Overhead is not applied to the machine line.** The machine rates in [`machines.md`](machines.md)
|
|
21
|
+
are loaded rates that already recover the shop's fixed costs. Applying overhead again is the
|
|
22
|
+
classic double-count and it makes us uncompetitive by 10–15 % without anyone noticing.
|
|
23
|
+
|
|
24
|
+
## Scrap and start-up
|
|
25
|
+
|
|
26
|
+
- **Process scrap 2.0 %** on an established tool, **3.5 % for the first 3 months** of a new tool.
|
|
27
|
+
We quote the established number and note the start-up allowance separately.
|
|
28
|
+
- **Start-up scrap** per production order: 15 shots, charged into the first order only.
|
|
29
|
+
- Glass-filled grades get **no regrind credit** (see `materials.md`).
|
|
30
|
+
|
|
31
|
+
## Labour
|
|
32
|
+
|
|
33
|
+
One operator covers **4 presses** on average, so the operator share per machine-hour is
|
|
34
|
+
`labour_rate / 4`. Manual work (deburring, insert loading, assembly) is quoted per part in
|
|
35
|
+
seconds and is *not* covered by that share.
|
|
36
|
+
|
|
37
|
+
## Packaging and freight
|
|
38
|
+
|
|
39
|
+
Standard is a returnable KLT with interleaves; one-way cartons on request. Freight is EXW, so it
|
|
40
|
+
is not in the piece price — but we state the packaging density because the customer's logistics
|
|
41
|
+
cost usually depends on it.
|
|
42
|
+
|
|
43
|
+
## Volume ladder and validity
|
|
44
|
+
|
|
45
|
+
- Piece prices are quoted at **10k / 50k / 250k parts per year** unless the customer states a
|
|
46
|
+
volume. Two things actually move along the ladder, and only two: **setup amortisation** over the
|
|
47
|
+
order size, and the **material price break** we get on annual tonnage (3 % above 2 t/year, 6 %
|
|
48
|
+
above 10 t/year — what our own supplier gives us, passed through). Nothing else is
|
|
49
|
+
volume-dependent, so a ladder that is nearly flat between two rungs is a correct answer, not a
|
|
50
|
+
missing discount.
|
|
51
|
+
- **Setup:** 3.5 h per production order at the machine rate, plus one drying charge. We plan up
|
|
52
|
+
to 12 orders a year but never below a **5 000-part minimum batch** — at low annual volume that
|
|
53
|
+
means fewer, larger runs, not twelve tool changes for a few hundred parts each.
|
|
54
|
+
- **Validity 30 days.** Material prices are indexed to the polymer index at order date; a change
|
|
55
|
+
above ±5 % is passed through.
|
|
56
|
+
|
|
57
|
+
```json commercial
|
|
58
|
+
{
|
|
59
|
+
"labour_rate_eur_h": 38.0,
|
|
60
|
+
"machines_per_operator": 4,
|
|
61
|
+
"overhead_pct_on_material_and_labour": 12.0,
|
|
62
|
+
"margin_pct": 15.0,
|
|
63
|
+
"scrap_pct_established": 2.0,
|
|
64
|
+
"scrap_pct_startup": 3.5,
|
|
65
|
+
"startup_shots_per_order": 15,
|
|
66
|
+
"setup_hours_per_order": 3.5,
|
|
67
|
+
"packaging_eur_per_part": 0.012,
|
|
68
|
+
"qc_eur_per_part": 0.008,
|
|
69
|
+
"orders_per_year": 12,
|
|
70
|
+
"min_order_parts": 5000,
|
|
71
|
+
"material_price_breaks": [
|
|
72
|
+
{"min_kg_per_year": 0, "discount_pct": 0.0},
|
|
73
|
+
{"min_kg_per_year": 2000, "discount_pct": 3.0},
|
|
74
|
+
{"min_kg_per_year": 10000, "discount_pct": 6.0}
|
|
75
|
+
],
|
|
76
|
+
"price_index_passthrough_pct": 5.0,
|
|
77
|
+
"amortisation_default_parts": 250000
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Tool amortisation
|
|
82
|
+
|
|
83
|
+
We show the tool as a lump sum **and** as an amortised cent-per-part figure over
|
|
84
|
+
`amortisation_default_parts`, so the customer can compare us with a supplier who hides the tool
|
|
85
|
+
in the piece price. We do not actually amortise unless the customer asks for it in writing —
|
|
86
|
+
an amortised tool that never reaches its volume is a loss we cannot recover.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Lessons — what we got wrong, and what changed because of it
|
|
2
|
+
|
|
3
|
+
**The agent reads this file first and writes to it last.** Every quote ends with a review: the
|
|
4
|
+
estimator corrects what the agent decided, says *why*, and the agent records it here — the reason
|
|
5
|
+
as prose, the number in the `calibration` block below. `quoting/costing.py` reads that block, so
|
|
6
|
+
a correction changes the **next** quote instead of being forgotten.
|
|
7
|
+
|
|
8
|
+
Do not delete entries. A superseded lesson is history, and knowing that a factor moved twice in
|
|
9
|
+
the same direction is itself information.
|
|
10
|
+
|
|
11
|
+
## The calibration block
|
|
12
|
+
|
|
13
|
+
These are the knobs the cost model exposes to this loop. Everything else lives in the other
|
|
14
|
+
`shop/` files — change those directly when the *shop* changes (a new press, a new rate). Change
|
|
15
|
+
**this** block when the *estimate was wrong*.
|
|
16
|
+
|
|
17
|
+
```json calibration
|
|
18
|
+
{
|
|
19
|
+
"clamp_safety_factor": 1.3,
|
|
20
|
+
"use_simulated_clamp_pressure": true,
|
|
21
|
+
"sim_peak_to_mean_pressure": 0.5,
|
|
22
|
+
"cooling_time_factor": 1.15,
|
|
23
|
+
"pack_time_s_per_mm_wall": 1.5,
|
|
24
|
+
"cycle_time_factor": 1.0,
|
|
25
|
+
"complexity_bonus": 0.0,
|
|
26
|
+
"tooling_price_factor": 1.00,
|
|
27
|
+
"piece_price_factor": 1.0
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
| Key | Meaning | Moved by |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `clamp_safety_factor` | multiplies the computed clamp force before picking a press | L-002 |
|
|
34
|
+
| `use_simulated_clamp_pressure` | if false, clamp comes from the material rule of thumb alone | — |
|
|
35
|
+
| `sim_peak_to_mean_pressure` | simulated **peak** cavity pressure → **mean** over the projected area | — |
|
|
36
|
+
| `cooling_time_factor` | multiplies the analytic cooling time | L-001 |
|
|
37
|
+
| `pack_time_s_per_mm_wall` | holding time per mm of **nominal** wall (gate freeze) | — |
|
|
38
|
+
| `cycle_time_factor` | last-resort factor on the whole cycle | — |
|
|
39
|
+
| `complexity_bonus` | added to the tooling complexity factor for every quote | — |
|
|
40
|
+
| `tooling_price_factor` | multiplies the final tool price | — |
|
|
41
|
+
| `piece_price_factor` | multiplies the final piece price | — |
|
|
42
|
+
|
|
43
|
+
## Entry format
|
|
44
|
+
|
|
45
|
+
```markdown
|
|
46
|
+
## L-00N · YYYY-MM-DD · <part> — <one-line title>
|
|
47
|
+
**Agent decided:** …
|
|
48
|
+
**Corrected to:** …
|
|
49
|
+
**Why (estimator's words):** …
|
|
50
|
+
**Rule for next time:** …
|
|
51
|
+
**Changed:** `calibration.<key>` A → B (or: nothing numeric — judgement only)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## L-001 · 2026-05-12 · bracket-A2 (PP TV20, 4 cav.) — cycle time was 12 % optimistic
|
|
57
|
+
|
|
58
|
+
**Agent decided:** cycle 21.4 s, from the analytic slab-cooling time on the p95 wall thickness.
|
|
59
|
+
|
|
60
|
+
**Corrected to:** 24.0 s. The tool ran at 24.3 s in production.
|
|
61
|
+
|
|
62
|
+
**Why (estimator's words):** "The textbook cooling time assumes perfect contact and a cooling
|
|
63
|
+
channel where you want it. On a ribbed part the ribs are the last thing to cool and we can't get
|
|
64
|
+
a channel into the rib root, so real cooling is always longer than the slab formula. On thin
|
|
65
|
+
flat parts the formula is fine — it's ribs and bosses that break it."
|
|
66
|
+
|
|
67
|
+
**Rule for next time:** apply a cooling-time factor above 1.0 by default; revisit it per part
|
|
68
|
+
family once we have three data points on flat parts vs ribbed parts.
|
|
69
|
+
|
|
70
|
+
**Changed:** `calibration.cooling_time_factor` 1.00 → 1.15
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## L-002 · 2026-06-03 · sensor-housing (PA6 GF30, 2 cav.) — clamp force undersized
|
|
75
|
+
|
|
76
|
+
**Agent decided:** 1100 kN required → Engel victory 110, from the simulated peak cavity pressure.
|
|
77
|
+
|
|
78
|
+
**Corrected to:** 1500 kN → Arburg 470 A 1500. The part flashed on the victory at trial.
|
|
79
|
+
|
|
80
|
+
**Why (estimator's words):** "The simulation models one cavity with no hot runner, so it doesn't
|
|
81
|
+
see the pressure drop through the manifold — the machine has to make that up and the cavity
|
|
82
|
+
pressure at the end of pack is far above the fill pressure the AI shows you. For glass-filled PA
|
|
83
|
+
we've always used 650 bar on the projected area and it has never let us down. Use the simulation
|
|
84
|
+
to decide *gates*, not to decide *tonnage*."
|
|
85
|
+
|
|
86
|
+
**Rule for next time:** clamp = max(simulation-derived, family rule of thumb) × safety factor,
|
|
87
|
+
and the safety factor goes up, not down. The simulation number is a lower bound, never the
|
|
88
|
+
answer. Say in the quotation which of the two governed.
|
|
89
|
+
|
|
90
|
+
**Changed:** `calibration.clamp_safety_factor` 1.20 → 1.30
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
<!-- New entries are appended here by `main.py learn`. -->
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Machines — the press list
|
|
2
|
+
|
|
3
|
+
> Fictional example fleet. Replace with yours. The cost model picks the **smallest machine that
|
|
4
|
+
> fits** (clamp force, shot volume, tie-bar opening) and bills its hourly rate.
|
|
5
|
+
|
|
6
|
+
## The fleet
|
|
7
|
+
|
|
8
|
+
| Press | Clamp | Shot (PS) | Screw | Tie-bar clear | Rate | Notes |
|
|
9
|
+
|---|---:|---:|---:|---|---:|---|
|
|
10
|
+
| Engel e-mac 50 | 500 kN | 62 cm³ | 25 mm | 320 × 320 mm | 42 €/h | all-electric, small precision work |
|
|
11
|
+
| Arburg 370 S 800 | 800 kN | 118 cm³ | 30 mm | 370 × 370 mm | 48 €/h | workhorse, hydraulic |
|
|
12
|
+
| Engel victory 110 | 1100 kN | 178 cm³ | 35 mm | 420 × 420 mm | 55 €/h | tie-bar-less — good for wide molds |
|
|
13
|
+
| Arburg 470 A 1500 | 1500 kN | 257 cm³ | 40 mm | 470 × 470 mm | 68 €/h | all-electric, our best cycle stability |
|
|
14
|
+
| KraussMaffei 250 CX | 2500 kN | 490 cm³ | 50 mm | 570 × 570 mm | 82 €/h | 2 units |
|
|
15
|
+
| Engel duo 400 | 4000 kN | 1080 cm³ | 70 mm | 720 × 720 mm | 105 €/h | largest tool we can run |
|
|
16
|
+
|
|
17
|
+
Rates are **machine + operator-share + energy + overhead recovery**, i.e. a loaded rate. They
|
|
18
|
+
already include the shop's fixed-cost recovery, so do **not** add overhead on top of the machine
|
|
19
|
+
line — overhead in [`commercial.md`](commercial.md) applies to material and labour only.
|
|
20
|
+
|
|
21
|
+
## Rules the agent must apply
|
|
22
|
+
|
|
23
|
+
- **Clamp:** the selected press needs `clamp_kN ≥ required_clamp_kN`. Required clamp comes from
|
|
24
|
+
mean cavity pressure × projected area of all cavities **plus the runner's projected area**,
|
|
25
|
+
times a safety factor. Never size a press at more than 80 % of its rated clamp — see
|
|
26
|
+
`max_clamp_utilisation` below.
|
|
27
|
+
- **Shot:** the shot volume (all cavities + runner) must sit between **20 % and 80 %** of the
|
|
28
|
+
press's rated shot volume. Under 20 % the residence time degrades the melt; over 80 % there is
|
|
29
|
+
no cushion. A part that only fits above 80 % gets the next press up.
|
|
30
|
+
- **Tie-bar:** the mold's plate footprint must clear the tie-bars. The victory 110 is tie-bar-less,
|
|
31
|
+
so it takes molds up to 700 × 700 mm despite the small clamp — that is why it is on the list.
|
|
32
|
+
- **Two shifts** are the planning assumption (see `shop-profile.md`). A quote that needs a third
|
|
33
|
+
shift or the weekend shift is a flagged note, not a silent price.
|
|
34
|
+
- If **no press fits**, say so plainly and quote the nearest external option as an assumption.
|
|
35
|
+
Do not silently scale the cavity count down — the cavity count is the customer's.
|
|
36
|
+
|
|
37
|
+
```json machines
|
|
38
|
+
{
|
|
39
|
+
"max_clamp_utilisation": 0.80,
|
|
40
|
+
"shot_utilisation_window": [0.20, 0.80],
|
|
41
|
+
"machines": [
|
|
42
|
+
{"name": "Engel e-mac 50", "clamp_kN": 500, "shot_cm3": 62, "screw_mm": 25, "tiebar_mm": [320, 320], "tiebarless": false, "rate_eur_h": 42},
|
|
43
|
+
{"name": "Arburg 370 S 800", "clamp_kN": 800, "shot_cm3": 118, "screw_mm": 30, "tiebar_mm": [370, 370], "tiebarless": false, "rate_eur_h": 48},
|
|
44
|
+
{"name": "Engel victory 110", "clamp_kN": 1100, "shot_cm3": 178, "screw_mm": 35, "tiebar_mm": [700, 700], "tiebarless": true, "rate_eur_h": 55},
|
|
45
|
+
{"name": "Arburg 470 A 1500", "clamp_kN": 1500, "shot_cm3": 257, "screw_mm": 40, "tiebar_mm": [470, 470], "tiebarless": false, "rate_eur_h": 68},
|
|
46
|
+
{"name": "KraussMaffei 250 CX","clamp_kN": 2500, "shot_cm3": 490, "screw_mm": 50, "tiebar_mm": [570, 570], "tiebarless": false, "rate_eur_h": 82},
|
|
47
|
+
{"name": "Engel duo 400", "clamp_kN": 4000, "shot_cm3": 1080, "screw_mm": 70, "tiebar_mm": [720, 720], "tiebarless": false, "rate_eur_h": 105}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Non-productive time per cycle
|
|
53
|
+
|
|
54
|
+
Mold open + eject + close + part removal, added to fill + pack + cool to get the cycle. Robot
|
|
55
|
+
take-out is standard on everything above 800 kN; the small presses drop parts to a conveyor.
|
|
56
|
+
|
|
57
|
+
```json cycle
|
|
58
|
+
{
|
|
59
|
+
"mold_open_close_s": 1.6,
|
|
60
|
+
"ejection_s": 0.8,
|
|
61
|
+
"part_removal_s": {"robot": 1.2, "freefall": 0.4},
|
|
62
|
+
"robot_from_clamp_kN": 800,
|
|
63
|
+
"oee": 0.85
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`oee` is the realistic availability factor applied to the theoretical cycle when converting to
|
|
68
|
+
capacity and to the piece price — 0.85 is our two-shift long-run average on established tools.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Materials — house grades and our bias
|
|
2
|
+
|
|
3
|
+
> Fictional example. Replace with your own grades and prices. This file is where the shop's
|
|
4
|
+
> **material bias** lives: what we buy, what we know how to run, and what we avoid.
|
|
5
|
+
|
|
6
|
+
## Our bias, stated plainly
|
|
7
|
+
|
|
8
|
+
We are a **PP / PA / POM shop**. Roughly 45 % of our shots are polypropylene (mostly talc- or
|
|
9
|
+
glass-filled automotive interior parts), 25 % polyamide (PA6 GF30 for under-hood and structural
|
|
10
|
+
brackets), 15 % POM (gears, latches, anything that has to slide), and the rest ABS/ASA and TPE
|
|
11
|
+
overmolds. We hold PP, PA6-GF30 and POM in silo or big-bag; everything else is bought per order
|
|
12
|
+
with a 3-week lead time and a minimum of 500 kg.
|
|
13
|
+
|
|
14
|
+
**What that means for a quote:**
|
|
15
|
+
|
|
16
|
+
- If the part shape allows it and the customer has not specified a grade, **propose a house
|
|
17
|
+
grade** — we run it better and buy it cheaper. Say that we proposed it.
|
|
18
|
+
- A non-house grade is quotable, but add the **procurement surcharge** and the lead time, and
|
|
19
|
+
flag the minimum order quantity — a 20k/year part in a bought-in grade carries a lot of
|
|
20
|
+
leftover material.
|
|
21
|
+
- **Never silently substitute.** If the customer named a grade, quote that grade. If we would
|
|
22
|
+
recommend another, put it on the assumptions slide as a proposal.
|
|
23
|
+
- Drying is not optional for PA and POM — it is in the piece price (see `drying_eur_per_kg`).
|
|
24
|
+
|
|
25
|
+
## When the customer has not named a material
|
|
26
|
+
|
|
27
|
+
Ask **once**, with a recommendation, and give the price impact. The question to ask:
|
|
28
|
+
|
|
29
|
+
> "The geometry doesn't imply a material. We'd default to **PP TV20 (talc-filled)** for a part
|
|
30
|
+
> like this — it's a house grade, ~1.85 €/kg, and it runs on our standard presses. If it needs
|
|
31
|
+
> stiffness or heat, **PA6 GF30** at ~3.40 €/kg. Which should I quote?"
|
|
32
|
+
|
|
33
|
+
If the user does not care, quote the house default (`default_grade` below) and mark it as an
|
|
34
|
+
assumption. Do **not** stall the quote waiting for a material answer.
|
|
35
|
+
|
|
36
|
+
## The grades we quote
|
|
37
|
+
|
|
38
|
+
| House grade | Family | Density | Price | Stock | Catalogue query | Stand-in |
|
|
39
|
+
|---|---|---:|---:|---|---|---|
|
|
40
|
+
| PP Generic | PP unfilled | 0.91 g/cm³ | 1.55 €/kg | silo | `PP Generic` | — |
|
|
41
|
+
| PP TV20 | PP + 20 % talc | 1.05 g/cm³ | 1.85 €/kg | silo | `PP T20` | `PP Generic` |
|
|
42
|
+
| PP GF30 | PP + 30 % glass | 1.13 g/cm³ | 2.60 €/kg | big-bag | `AKROLEN PP GF30` | `PP Generic` |
|
|
43
|
+
| PA6 GF30 | PA6 + 30 % glass | 1.36 g/cm³ | 3.40 €/kg | big-bag | `ALCOM PA6 900/8 GF10` | `PA66 Generic` |
|
|
44
|
+
| POM C | POM copolymer | 1.41 g/cm³ | 3.10 €/kg | big-bag | `POM Generic` | — |
|
|
45
|
+
| ABS | ABS | 1.05 g/cm³ | 2.35 €/kg | per order | `ABS Generic` | — |
|
|
46
|
+
|
|
47
|
+
**Catalogue names are not house names, and our compounds are often not in the catalogue at all.**
|
|
48
|
+
Resolve the grade against the platform's material catalogue before simulating
|
|
49
|
+
(`GET /materials?q=…`), take the `material_id` and the version's recommended melt/mould
|
|
50
|
+
temperatures, and record *which* catalogue entry you used.
|
|
51
|
+
|
|
52
|
+
When the grade is not there — `PP TV20` is not, and the catalogue holds no talc-filled PP at all —
|
|
53
|
+
the search falls back to the **stand-in named above**, then to the family's `… Generic` grade. It
|
|
54
|
+
never silently takes "the first search hit": a search for `PP` returns a GF30 compound first, and
|
|
55
|
+
simulating a glass-filled rheology for an unfilled part would be worse than not simulating. Any
|
|
56
|
+
substitution is carried onto the quote's assumptions slide.
|
|
57
|
+
|
|
58
|
+
## Cavity-pressure rule of thumb (used for clamp sizing)
|
|
59
|
+
|
|
60
|
+
The AI filling solver models **one cavity with no runner system**, and is known to under-read
|
|
61
|
+
absolute pressure on multi-gate parts. So clamp force is **never** sized from the simulation
|
|
62
|
+
alone. We take the larger of (simulation-derived mean pressure) and (the family rule of thumb
|
|
63
|
+
below), then apply the safety factor from [`lessons.md`](lessons.md).
|
|
64
|
+
|
|
65
|
+
| Family | Mean cavity pressure for clamp |
|
|
66
|
+
|---|---|
|
|
67
|
+
| PP unfilled / talc | 350 bar |
|
|
68
|
+
| PP GF / ABS | 450 bar |
|
|
69
|
+
| PA6 GF30 | 650 bar |
|
|
70
|
+
| POM | 550 bar |
|
|
71
|
+
|
|
72
|
+
```json materials
|
|
73
|
+
{
|
|
74
|
+
"default_grade": "PP TV20",
|
|
75
|
+
"procurement_surcharge_pct": 8.0,
|
|
76
|
+
"non_stock_lead_weeks": 3,
|
|
77
|
+
"non_stock_moq_kg": 500,
|
|
78
|
+
"drying_eur_per_kg": 0.06,
|
|
79
|
+
"grades": [
|
|
80
|
+
{"name": "PP Generic", "family": "PP", "density_g_cm3": 0.91, "price_eur_kg": 1.55, "stock": "silo", "catalogue_query": "PP Generic", "catalogue_fallback": "PP Generic", "clamp_pressure_bar": 350, "regrind_pct": 15, "dry": false},
|
|
81
|
+
{"name": "PP TV20", "family": "PP", "density_g_cm3": 1.05, "price_eur_kg": 1.85, "stock": "silo", "catalogue_query": "PP T20", "catalogue_fallback": "PP Generic", "clamp_pressure_bar": 350, "regrind_pct": 15, "dry": false},
|
|
82
|
+
{"name": "PP GF30", "family": "PP-GF", "density_g_cm3": 1.13, "price_eur_kg": 2.60, "stock": "big-bag", "catalogue_query": "AKROLEN PP GF30", "catalogue_fallback": "PP Generic", "clamp_pressure_bar": 450, "regrind_pct": 0, "dry": false},
|
|
83
|
+
{"name": "PA6 GF30", "family": "PA-GF", "density_g_cm3": 1.36, "price_eur_kg": 3.40, "stock": "big-bag", "catalogue_query": "ALCOM PA6 900/8 GF10", "catalogue_fallback": "PA66 Generic", "clamp_pressure_bar": 650, "regrind_pct": 0, "dry": true},
|
|
84
|
+
{"name": "POM C", "family": "POM", "density_g_cm3": 1.41, "price_eur_kg": 3.10, "stock": "big-bag", "catalogue_query": "POM Generic", "catalogue_fallback": "POM Generic", "clamp_pressure_bar": 550, "regrind_pct": 10, "dry": true},
|
|
85
|
+
{"name": "ABS", "family": "ABS", "density_g_cm3": 1.05, "price_eur_kg": 2.35, "stock": "per order", "catalogue_query": "ABS Generic", "catalogue_fallback": "ABS Generic", "clamp_pressure_bar": 450, "regrind_pct": 10, "dry": true}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`regrind_pct` is how much of the sprue/runner we are allowed to feed back for that family — it
|
|
91
|
+
reduces the material line on a cold-runner tool. Zero for glass-filled grades (fibre breakage)
|
|
92
|
+
and for anything the customer has spec'd as virgin.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Shop profile — Feldmann Formenbau & Spritzguss GmbH
|
|
2
|
+
|
|
3
|
+
> **`provenance: example` — this is a fictional shop.** Every press, rate and margin below is
|
|
4
|
+
> invented. Until someone runs the interview (`python main.py setup`, script in
|
|
5
|
+
> [`../INTERVIEW.md`](../INTERVIEW.md)) and flips `provenance` to their own shop's name, every
|
|
6
|
+
> quote is watermarked as built on example data, because a quote against someone else's fictional
|
|
7
|
+
> rates is worse than no quote at all.
|
|
8
|
+
>
|
|
9
|
+
> The agent quotes as *this* shop, so every sentence here changes what it offers and what it
|
|
10
|
+
> refuses. Keep it as a worked reference for what "filled in" looks like; replace the values.
|
|
11
|
+
|
|
12
|
+
## What we are
|
|
13
|
+
|
|
14
|
+
A 62-person **moldmaker with an attached molding shop** in Lüdenscheid (NRW). Two thirds of
|
|
15
|
+
revenue is tooling; one third is molded parts. We build the tool, sample it on our own presses,
|
|
16
|
+
and — for most customers — also run the series.
|
|
17
|
+
|
|
18
|
+
## What we do in-house
|
|
19
|
+
|
|
20
|
+
| | In-house | Notes |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| Mold design (CAD) | ✅ | Siemens NX, 2 designers |
|
|
23
|
+
| Cavity/core milling, EDM, wire | ✅ | 5-axis HSC, 3 sinkers |
|
|
24
|
+
| Hardening, coating | ❌ | bought in (a hardening shop, +2 weeks) |
|
|
25
|
+
| Texturing / graining | ❌ | bought in (a texturing house, +3 weeks) |
|
|
26
|
+
| **Mold trials (sampling)** | ✅ | on our own presses — **always priced into the tool**, 2 shots included |
|
|
27
|
+
| **Series production** | ✅ | 12 presses, 2-shift + optional weekend shift |
|
|
28
|
+
| Assembly / pad printing | partial | manual assembly cells only |
|
|
29
|
+
| Metrology | ✅ | Zeiss CMM, first-article inspection reports |
|
|
30
|
+
|
|
31
|
+
**Consequence for quoting:** we quote **tool + piece price together** by default. A tool-only
|
|
32
|
+
quote is possible but we then add a sampling package as a separate line — we never hand over an
|
|
33
|
+
unsampled mold.
|
|
34
|
+
|
|
35
|
+
## What we are good at, and what we decline
|
|
36
|
+
|
|
37
|
+
- **Sweet spot:** technical parts, 50–400 g shot weight, 1–8 cavities, PP / PA / POM / ABS,
|
|
38
|
+
annual volumes 20k–500k.
|
|
39
|
+
- **We decline:** Class-A cosmetic exteriors (no paint line, no texture bench of our own),
|
|
40
|
+
micro-molding under 1 g, LSR, and multi-component tools with more than 2 materials.
|
|
41
|
+
- **We are cautious with:** unfilled PA (moisture handling), parts with wall thickness under
|
|
42
|
+
0.8 mm, and anything with a tolerance tighter than IT10 on a shrinking dimension — those get
|
|
43
|
+
a flagged assumption, not a silent price.
|
|
44
|
+
|
|
45
|
+
## How we quote (the house rules the agent must follow)
|
|
46
|
+
|
|
47
|
+
1. **Piece price is quoted at a volume ladder**, not at one number — 10k / 50k / 250k parts per
|
|
48
|
+
year — unless the customer states a volume. We do not ask for a volume just to produce a
|
|
49
|
+
number; we state the ladder and the assumption.
|
|
50
|
+
2. **Tooling is quoted as a lump sum** with a lead time in weeks, amortisation shown separately
|
|
51
|
+
(we do not hide tool cost in the piece price unless the customer asks for it).
|
|
52
|
+
3. **The cavity count is the customer's**, not ours to change. If the simulation says the count
|
|
53
|
+
is a bad idea (machine too large, pressure marginal, weld line on a functional face), we say
|
|
54
|
+
so as a flagged note and quote what was asked anyway.
|
|
55
|
+
4. **Every assumption is written down.** A quote with an unstated assumption is how we lose
|
|
56
|
+
money — stating the assumptions in the quotation is not optional.
|
|
57
|
+
5. **Validity 30 days**, material prices indexed (see [`commercial.md`](commercial.md)).
|
|
58
|
+
|
|
59
|
+
## Standard commercial position
|
|
60
|
+
|
|
61
|
+
- Currency **EUR**, prices ex works Lüdenscheid, Incoterms EXW.
|
|
62
|
+
- Tooling payment 50 % order / 40 % first article / 10 % approval.
|
|
63
|
+
- Series: 30 days net, minimum call-off 1 month of forecast.
|
|
64
|
+
- Tool ownership passes to the customer on final payment; the tool stays in our shop.
|
|
65
|
+
|
|
66
|
+
```json shop
|
|
67
|
+
{
|
|
68
|
+
"provenance": "example",
|
|
69
|
+
"name": "Feldmann Formenbau & Spritzguss GmbH",
|
|
70
|
+
"location": "Lüdenscheid, DE",
|
|
71
|
+
"currency": "EUR",
|
|
72
|
+
"services": {
|
|
73
|
+
"mold_design": true,
|
|
74
|
+
"mold_making": true,
|
|
75
|
+
"mold_trials": true,
|
|
76
|
+
"series_production": true,
|
|
77
|
+
"texturing_in_house": false,
|
|
78
|
+
"hardening_in_house": false
|
|
79
|
+
},
|
|
80
|
+
"volume_ladder_parts_per_year": [10000, 50000, 250000],
|
|
81
|
+
"quote_validity_days": 30,
|
|
82
|
+
"shifts_per_day": 2,
|
|
83
|
+
"production_hours_per_year": 3800,
|
|
84
|
+
"declines": ["class-a cosmetic exterior", "micro molding < 1 g", "LSR", "3+ component tools"],
|
|
85
|
+
"caution": ["wall thickness < 0.8 mm", "unfilled PA", "tolerance tighter than IT10"]
|
|
86
|
+
}
|
|
87
|
+
```
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Tooling — how we price a mold
|
|
2
|
+
|
|
3
|
+
> Fictional example cost model. Replace the numbers with your own estimating basis; keep the
|
|
4
|
+
> structure, because [`quoting/costing.py`](../quoting/costing.py) reads the block at the bottom.
|
|
5
|
+
|
|
6
|
+
## The estimating basis
|
|
7
|
+
|
|
8
|
+
We estimate a mold as **base + cavities + the things that make it complicated**, not as a
|
|
9
|
+
€/kg-of-steel figure. The five lines that decide the price:
|
|
10
|
+
|
|
11
|
+
1. **Mold base** — driven by the plate footprint, which comes from the part's projected size, the
|
|
12
|
+
cavity layout, and the space the runner and cooling need.
|
|
13
|
+
2. **Cavity + core machining** — per cavity, scaled by a complexity factor derived from the
|
|
14
|
+
geometry (surface area, wall thinness, feature count).
|
|
15
|
+
3. **Side actions** — every undercut that cannot be released in the draw direction is a slide or
|
|
16
|
+
a lifter. This is the single most common reason a tool quote goes wrong: **count them from the
|
|
17
|
+
geometry, do not assume there are none.**
|
|
18
|
+
4. **Feed system** — a hot runner costs real money per drop, and **the number of drops is the
|
|
19
|
+
number of gates the filling study decides**. This is why the study runs before the quote and
|
|
20
|
+
not after it: one extra gate per cavity on a 4-cavity tool is four more nozzles.
|
|
21
|
+
5. **Cooling, ejection, finish, sampling** — smaller lines, but they add up to 20–30 % of the
|
|
22
|
+
tool.
|
|
23
|
+
|
|
24
|
+
## Rules
|
|
25
|
+
|
|
26
|
+
- **Standard construction is a 2-plate tool with a hot runner** for anything above 2 cavities;
|
|
27
|
+
below that we compare against a cold runner and quote the cheaper total (tool + material over
|
|
28
|
+
the volume ladder). A cold runner is not "cheaper" once you price the runner scrap over
|
|
29
|
+
250k parts.
|
|
30
|
+
- **Cavity layout** is a balanced grid (1, 2, 4, 6, 8…). An unbalanced layout (3, 5) needs a
|
|
31
|
+
naturally-balanced runner and costs a slide-equivalent in design time — flag it.
|
|
32
|
+
- **We include 2 sampling shots**; further loops are chargeable and quoted per shot.
|
|
33
|
+
- **Hardening and texturing are bought in** — they add cost *and* weeks, and the weeks are
|
|
34
|
+
usually what the customer actually cares about.
|
|
35
|
+
- **Steel choice** follows the volume ladder: 1.2311 pre-hardened up to 100k parts/year,
|
|
36
|
+
1.2343 ESU hardened above that, glass-filled grades always hardened.
|
|
37
|
+
- **Tool lifetime guarantee:** 500k shots on hardened steel, 250k on pre-hardened, subject to
|
|
38
|
+
our maintenance contract.
|
|
39
|
+
|
|
40
|
+
## Complexity factor — how we judge "complicated"
|
|
41
|
+
|
|
42
|
+
The factor multiplies the cavity machining line. It starts at 1.0 and moves with what the
|
|
43
|
+
geometry actually shows:
|
|
44
|
+
|
|
45
|
+
| Signal | Effect |
|
|
46
|
+
|---|---|
|
|
47
|
+
| thin walls (nominal < 1.2 mm) | +0.15 — harder to fill, tighter tolerance on the steel |
|
|
48
|
+
| deep draw (depth > 60 mm) | +0.15 |
|
|
49
|
+
| **shape factor** above 1.0 | +0.25 per unit — part surface vs. its bounding-box surface, i.e. how much rib, boss and pocket is in there |
|
|
50
|
+
| undercuts present | already priced as slides; +0.05 each for the fitting work |
|
|
51
|
+
| textured or polished finish | priced separately, see `finish_eur_per_cm2` |
|
|
52
|
+
|
|
53
|
+
> **Not** surface-to-volume ratio, which looks like the same thing and is not: it mostly measures
|
|
54
|
+
> wall thinness, so a plain 1.5 mm plate scores 15 on it and would be priced as a hard cavity.
|
|
55
|
+
> A flat part has a shape factor near or below 1; a ribbed housing goes well above it.
|
|
56
|
+
|
|
57
|
+
Cap it at 1.8. Above that we are not estimating any more, we are guessing — say so and quote
|
|
58
|
+
after a design review.
|
|
59
|
+
|
|
60
|
+
```json tooling
|
|
61
|
+
{
|
|
62
|
+
"layout": {
|
|
63
|
+
"cavity_spacing_mm": 45,
|
|
64
|
+
"edge_margin_mm": 60,
|
|
65
|
+
"min_plate_mm": [246, 246],
|
|
66
|
+
"max_plate_mm": [720, 720],
|
|
67
|
+
"preferred_grids": {"1": [1, 1], "2": [2, 1], "4": [2, 2], "6": [3, 2], "8": [4, 2], "12": [4, 3], "16": [4, 4]}
|
|
68
|
+
},
|
|
69
|
+
"base": {
|
|
70
|
+
"fixed_eur": 1200,
|
|
71
|
+
"eur_per_cm2_plate": 2.2,
|
|
72
|
+
"guided_ejector_eur": 850
|
|
73
|
+
},
|
|
74
|
+
"cavity": {
|
|
75
|
+
"fixed_eur_per_cavity": 2500,
|
|
76
|
+
"eur_per_cm2_part_surface": 15.0,
|
|
77
|
+
"complexity_cap": 1.8,
|
|
78
|
+
"hardened_surcharge_eur_per_cavity": 900,
|
|
79
|
+
"hardened_lead_weeks": 2
|
|
80
|
+
},
|
|
81
|
+
"side_actions": {
|
|
82
|
+
"slide_eur": 3200,
|
|
83
|
+
"lifter_eur": 1900,
|
|
84
|
+
"undercut_area_mm2_per_action": 400
|
|
85
|
+
},
|
|
86
|
+
"feed_system": {
|
|
87
|
+
"hot_runner_controller_eur": 2400,
|
|
88
|
+
"hot_runner_nozzle_eur": 1850,
|
|
89
|
+
"hot_runner_manifold_eur": 2800,
|
|
90
|
+
"cold_runner_eur": 900,
|
|
91
|
+
"cold_runner_volume_cm3_per_drop": 4.5,
|
|
92
|
+
"hot_runner_from_cavities": 3
|
|
93
|
+
},
|
|
94
|
+
"cooling": {
|
|
95
|
+
"circuit_eur": 420,
|
|
96
|
+
"cm2_plate_per_circuit": 450,
|
|
97
|
+
"min_circuits": 4,
|
|
98
|
+
"conformal_surcharge_eur": 0
|
|
99
|
+
},
|
|
100
|
+
"ejection": {
|
|
101
|
+
"fixed_eur": 1500,
|
|
102
|
+
"pin_eur": 55,
|
|
103
|
+
"pins_per_cavity_per_cm2_projected": 0.06,
|
|
104
|
+
"min_pins_per_cavity": 4
|
|
105
|
+
},
|
|
106
|
+
"finish": {
|
|
107
|
+
"technical_eur_per_cm2": 1.2,
|
|
108
|
+
"polished_eur_per_cm2": 4.5,
|
|
109
|
+
"textured_eur_per_cm2": 2.8,
|
|
110
|
+
"texturing_lead_weeks": 3,
|
|
111
|
+
"default": "technical"
|
|
112
|
+
},
|
|
113
|
+
"engineering": {
|
|
114
|
+
"design_rate_eur_h": 85,
|
|
115
|
+
"design_hours_base": 24,
|
|
116
|
+
"design_hours_per_cavity": 6,
|
|
117
|
+
"design_hours_per_side_action": 8,
|
|
118
|
+
"project_mgmt_pct": 6.0
|
|
119
|
+
},
|
|
120
|
+
"sampling": {
|
|
121
|
+
"shots_included": 2,
|
|
122
|
+
"eur_per_shot": 1600,
|
|
123
|
+
"extra_shot_eur": 1200
|
|
124
|
+
},
|
|
125
|
+
"lead_time": {
|
|
126
|
+
"base_weeks": 8,
|
|
127
|
+
"weeks_per_extra_cavity": 0.4,
|
|
128
|
+
"weeks_per_side_action": 0.8,
|
|
129
|
+
"hot_runner_weeks": 2,
|
|
130
|
+
"sampling_weeks": 2
|
|
131
|
+
},
|
|
132
|
+
"margin_pct": 18.0,
|
|
133
|
+
"risk_contingency_pct": 5.0
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## What is *not* in the model
|
|
138
|
+
|
|
139
|
+
Deliberately, so the agent flags them instead of pricing them wrong:
|
|
140
|
+
|
|
141
|
+
- **Multi-component / 2K tools** — out of scope (see `shop-profile.md`).
|
|
142
|
+
- **Unscrewing cores** for threads — priced by design review, roughly 2× a slide.
|
|
143
|
+
- **Conformal cooling** — we buy it in per project; `conformal_surcharge_eur` is 0 because we
|
|
144
|
+
quote it separately when the cooling study says the part needs it.
|
|
145
|
+
- **Spare parts package** — quoted on request, typically 8 % of the tool.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# What this template writes when it runs. A generated project receives THIS file and not the
|
|
2
|
+
# kit's root one, so the rules have to live here or a customer's first commit carries their
|
|
3
|
+
# own simulation results.
|
|
4
|
+
#
|
|
5
|
+
# build/ holds the .h5 the run produces and the inputs recorded beside it. Safe to delete.
|
|
6
|
+
build/
|
|
7
|
+
*.h5
|
|
8
|
+
|
|
9
|
+
.venv/
|
|
10
|
+
__pycache__/
|
|
11
|
+
*.pyc
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
|
|
14
|
+
# never commit credentials
|
|
15
|
+
*token*.json
|
|
16
|
+
.env
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Run one simulation — how to drive this template
|
|
2
|
+
|
|
3
|
+
The smallest end-to-end run: mesh a part, upload it, pick a material, run one AI filling
|
|
4
|
+
simulation, read the peak pressure back. Start here when someone wants to see the platform
|
|
5
|
+
work at all, or when a single answer is the whole task.
|
|
6
|
+
|
|
7
|
+
## What to run
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
python main.py # the bundled sample part
|
|
11
|
+
python main.py --part path/to/part.stl # your own geometry
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
There is one script and no subcommands. A run takes seconds and writes the result under
|
|
15
|
+
`build/`.
|
|
16
|
+
|
|
17
|
+
## What is in this folder
|
|
18
|
+
|
|
19
|
+
- `main.py` is the whole workflow, top to bottom, meant to be read.
|
|
20
|
+
- `cadmould_geometry/` meshes the part; `cadmould_results/` opens the result file.
|
|
21
|
+
- `sample/` holds the default geometry. It is ours — replace the file with your own and
|
|
22
|
+
`python main.py` keeps working, or delete the folder and always pass `--part`.
|
|
23
|
+
- `build/` is where the downloaded result lands. It is yours and it is safe to delete.
|
|
24
|
+
|
|
25
|
+
## Things to get right here
|
|
26
|
+
|
|
27
|
+
**Everything happens inside one licence session**, `set_base_url` included. The script is
|
|
28
|
+
written that way and it is the shape to copy — see the rule above on nesting.
|
|
29
|
+
|
|
30
|
+
**The result opens in the web viewer.** Every simulation returns a viewer URL; this kit
|
|
31
|
+
renders nothing locally, so hand the engineer the link rather than trying to draw the field.
|
|
32
|
+
|
|
33
|
+
**Reading the result is the interesting part.** `main.py` pulls one number out. If you are
|
|
34
|
+
asked for more, open the file with `cadmould_results` rather than reaching for h5py, and
|
|
35
|
+
apply the result-reading rules above.
|
|
36
|
+
|
|
37
|
+
## Going further
|
|
38
|
+
|
|
39
|
+
This template uses the `cadmould.cloud` SDK, which does not wrap projects, groups or the
|
|
40
|
+
decision log. If the task grows into a real study, that needs a REST client — the gate-study
|
|
41
|
+
workflow is the worked example.
|