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,232 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cadmould-api-toolkit-starter-kit"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Getting-started kit for the Simcon cadmould Python SDK and cloud platform: docs plus four ready-to-run templates."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
# A supported window, not the SDK's whole wheel range. The floor is the Python in
|
|
11
|
+
# Ubuntu 24.04 LTS (supported to 2029) and the one our own platform runs; the ceiling
|
|
12
|
+
# is the current release, which is also the Python in Ubuntu 26.04 LTS. CI tests both
|
|
13
|
+
# ends, and tests/test_repository_layout.py fails if the two ever disagree.
|
|
14
|
+
# ⚠️ The upper bound is a standing chore: 3.15 arrives in October 2026 and anyone on it
|
|
15
|
+
# is refused until this line and the CI matrix are bumped together.
|
|
16
|
+
requires-python = ">=3.12,<3.15"
|
|
17
|
+
# Apache-2.0: same convention as cadmould-sdk-auth — the starter kit is OSS, the
|
|
18
|
+
# cadmould SDK it demonstrates stays proprietary. SPDX expression (PEP 639); the
|
|
19
|
+
# license-files default picks up LICENSE and NOTICE. No License:: classifier —
|
|
20
|
+
# deprecated alongside an SPDX expression.
|
|
21
|
+
license = "Apache-2.0"
|
|
22
|
+
authors = [{ name = "SIMCON kunststofftechnische Software GmbH" }]
|
|
23
|
+
keywords = ["cadmould", "simcon", "injection-molding", "simulation", "sdk"]
|
|
24
|
+
classifiers = [
|
|
25
|
+
"Programming Language :: Python :: 3",
|
|
26
|
+
"Intended Audience :: Developers",
|
|
27
|
+
"Topic :: Scientific/Engineering",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
# Shared runtime dependencies every template uses. The licensed `cadmould` SDK
|
|
31
|
+
# lives on Simcon's private index (AWS CodeArtifact); after running
|
|
32
|
+
# `cadmould-sdk-auth` the index is configured and pip resolves it normally.
|
|
33
|
+
dependencies = [
|
|
34
|
+
"cadmould>=0.1.0",
|
|
35
|
+
"numpy>=1.26",
|
|
36
|
+
"h5py>=3.10",
|
|
37
|
+
# Reads STL into vertex and face arrays. numpy is its only dependency and it costs
|
|
38
|
+
# about 3 MB, where the graphics stack it replaced cost roughly 600 MB to do the same job.
|
|
39
|
+
"trimesh>=4.0",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
# Per-template extras — the single source for each template's open deps. Install only
|
|
43
|
+
# what you need, e.g. `pip install ".[gate-study]"` (or `".[templates]"` for all of them).
|
|
44
|
+
#
|
|
45
|
+
# matplotlib, python-pptx and pillow are deliberately absent: the kit no longer renders
|
|
46
|
+
# images or builds decks. A result is opened in the web viewer via the URL the API
|
|
47
|
+
# returns, and a customer's own assistant writes whatever document they want.
|
|
48
|
+
#
|
|
49
|
+
# The graphics stack is gone entirely. quoting was its last user, for ray-casting the
|
|
50
|
+
# geometry; that measurement is now trimesh's, which is both a core dependency already and
|
|
51
|
+
# the only one of the two that gives the same answer twice.
|
|
52
|
+
[project.optional-dependencies]
|
|
53
|
+
# Declares nothing beyond the core dependencies. It stays listed because a template
|
|
54
|
+
# directory with no extra of its own is one nobody can install.
|
|
55
|
+
run-one-simulation = []
|
|
56
|
+
gate-study = ["httpx>=0.27", "scipy>=1.11"]
|
|
57
|
+
quoting = [
|
|
58
|
+
"rtree>=1.0", # spatial index behind trimesh's thickness and ray queries (~2 MB)
|
|
59
|
+
"httpx>=0.27", # cloud REST + the Auth0 PKCE login
|
|
60
|
+
"scipy>=1.11", # KD-tree behind weld detection (metrics.knn_indices)
|
|
61
|
+
]
|
|
62
|
+
process-window = ["httpx>=0.27", "pyyaml>=6.0", "scipy>=1.11"]
|
|
63
|
+
# Everything the templates need, in one shot. ⚠️ Nothing checks this against the union of
|
|
64
|
+
# the per-template extras above — `AGGREGATE_EXTRAS` in tests/_layout.py only SUBTRACTS the
|
|
65
|
+
# aggregates so they are not mistaken for templates. What the suite does check is that a
|
|
66
|
+
# template directory and its own extra agree. Keeping this list correct is by hand.
|
|
67
|
+
templates = [
|
|
68
|
+
"rtree>=1.0",
|
|
69
|
+
"httpx>=0.27",
|
|
70
|
+
"pyyaml>=6.0",
|
|
71
|
+
"scipy>=1.11",
|
|
72
|
+
]
|
|
73
|
+
# Kept as an extra for `pip install -e ".[test]"` compatibility. scipy is here because the
|
|
74
|
+
# weld-detection golden test drives the scoring module, which resolves neighbours with it.
|
|
75
|
+
test = ["pytest>=7", "scipy>=1.11"]
|
|
76
|
+
|
|
77
|
+
[project.urls]
|
|
78
|
+
Homepage = "https://github.com/Simcon-Software/cadmould-api-toolkit-starter-kit"
|
|
79
|
+
Repository = "https://github.com/Simcon-Software/cadmould-api-toolkit-starter-kit"
|
|
80
|
+
Documentation = "https://api.simcon.ai/scalar"
|
|
81
|
+
|
|
82
|
+
# Developer tooling in a PEP 735 dependency group (as in cadmould-sdk-auth). CI and local dev
|
|
83
|
+
# install it with `pip install --upgrade pip && pip install --group dev` — the `--group` flag
|
|
84
|
+
# needs pip >= 25.1, newer than the pip bundled with Python 3.12.
|
|
85
|
+
[dependency-groups]
|
|
86
|
+
dev = [
|
|
87
|
+
# Source of truth for the ruff version. CI installs ruff via `--group dev`; the only other
|
|
88
|
+
# copy is `.pre-commit-config.yaml`'s `rev` (it can't read pyproject) — keep the two equal.
|
|
89
|
+
"ruff==0.15.16",
|
|
90
|
+
"pre-commit>=3.5",
|
|
91
|
+
"pytest>=7",
|
|
92
|
+
]
|
|
93
|
+
|
|
94
|
+
# This project is the kit's own development environment, and it is deliberately never
|
|
95
|
+
# published: it declares the licensed `cadmould` wheel, so a customer resolving it
|
|
96
|
+
# against public PyPI would be refused. It ships no packages for the same reason —
|
|
97
|
+
# pyproject.toml here exists for project metadata, dependency groups and tool
|
|
98
|
+
# configuration.
|
|
99
|
+
#
|
|
100
|
+
# The published artefact is a SECOND project, `cli/`, which declares nothing but its prompt
|
|
101
|
+
# library and carries the templates, the shared libraries, the sample geometry and the
|
|
102
|
+
# manifest inside its own wheel. tests/test_wheel_contents.py builds it and checks that
|
|
103
|
+
# every one of those files arrived.
|
|
104
|
+
[tool.setuptools]
|
|
105
|
+
packages = []
|
|
106
|
+
|
|
107
|
+
# --- Ruff ----------------------------------------------------------------
|
|
108
|
+
# One rule set for the whole tree. Template code is what customers read and copy, so
|
|
109
|
+
# it is linted like everything else — the blanket amnesty it used to carry excused
|
|
110
|
+
# twelve rule families and hid 970 findings.
|
|
111
|
+
#
|
|
112
|
+
# The selection matches what comparable projects apply to their own teaching code
|
|
113
|
+
# (FastAPI's docs_src, Typer's docs_src): correctness, imports, modernisation and
|
|
114
|
+
# simplification. Annotations (ANN), docstrings (D) and naming (N) are deliberately
|
|
115
|
+
# NOT selected repo-wide — none of those projects selects them for any code, they
|
|
116
|
+
# accounted for 777 of the 970 findings, and annotating every template function makes
|
|
117
|
+
# a tutorial denser rather than clearer. `packages/` is held to a higher bar instead,
|
|
118
|
+
# via its own config file, because that is a library customers import.
|
|
119
|
+
#
|
|
120
|
+
# Exceptions are narrow and each carries its reason: per-file `noqa` for a specific
|
|
121
|
+
# rule, never a directory waved through. tests/ keeps the exemptions every project
|
|
122
|
+
# gives tests.
|
|
123
|
+
[tool.ruff]
|
|
124
|
+
line-length = 120
|
|
125
|
+
target-version = "py312"
|
|
126
|
+
# Never auto-fix implicitly: `ruff check` (no flag) must not rewrite files.
|
|
127
|
+
# Use `ruff check --fix` / `ruff format` explicitly.
|
|
128
|
+
fix = false
|
|
129
|
+
# Honour `exclude` even when pre-commit passes file paths explicitly.
|
|
130
|
+
force-exclude = true
|
|
131
|
+
exclude = [
|
|
132
|
+
".git",
|
|
133
|
+
".ruff_cache",
|
|
134
|
+
".venv",
|
|
135
|
+
"venv",
|
|
136
|
+
"build",
|
|
137
|
+
"dist",
|
|
138
|
+
"node_modules",
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
[tool.ruff.lint]
|
|
142
|
+
select = [
|
|
143
|
+
"E", # pycodestyle errors
|
|
144
|
+
"F", # pyflakes
|
|
145
|
+
"W", # pycodestyle warnings
|
|
146
|
+
"I", # isort
|
|
147
|
+
"UP", # pyupgrade
|
|
148
|
+
"B", # flake8-bugbear
|
|
149
|
+
"C4", # flake8-comprehensions
|
|
150
|
+
"PT", # pytest style
|
|
151
|
+
"SIM", # flake8-simplify
|
|
152
|
+
"Q", # flake8-quotes
|
|
153
|
+
# A `noqa` naming a rule this repository does not enable suppresses nothing, and
|
|
154
|
+
# tells a reader the opposite. Five such comments shipped inside the published wheel.
|
|
155
|
+
"RUF100", # unused-noqa
|
|
156
|
+
]
|
|
157
|
+
ignore = [
|
|
158
|
+
# Line length is the formatter's job; the linter flagging it too is noise.
|
|
159
|
+
"E501",
|
|
160
|
+
]
|
|
161
|
+
fixable = ["ALL"]
|
|
162
|
+
unfixable = []
|
|
163
|
+
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
|
164
|
+
|
|
165
|
+
# `D` is not selected repo-wide, so this setting does nothing here today. It is kept
|
|
166
|
+
# because `packages/` will select `D` through a config file that extends this one, and
|
|
167
|
+
# the convention has to be inherited rather than restated there.
|
|
168
|
+
[tool.ruff.lint.pydocstyle]
|
|
169
|
+
convention = "google"
|
|
170
|
+
|
|
171
|
+
[tool.ruff.lint.mccabe]
|
|
172
|
+
max-complexity = 10
|
|
173
|
+
|
|
174
|
+
[tool.ruff.lint.isort]
|
|
175
|
+
# Both the names that exist today and the ones the restructure creates. isort ignores a
|
|
176
|
+
# name that matches nothing, so listing both keeps every intermediate state sorted the same.
|
|
177
|
+
known-first-party = [
|
|
178
|
+
"cadmould",
|
|
179
|
+
# Our own tooling, not a template dependency: the code that assembles a project, and
|
|
180
|
+
# the installer it lives in.
|
|
181
|
+
"generator",
|
|
182
|
+
"simcon_toolkit",
|
|
183
|
+
"cadmould_cloud",
|
|
184
|
+
"cadmould_geometry",
|
|
185
|
+
"cadmould_results",
|
|
186
|
+
"cadmould_scoring",
|
|
187
|
+
]
|
|
188
|
+
split-on-trailing-comma = true
|
|
189
|
+
combine-as-imports = true
|
|
190
|
+
|
|
191
|
+
[tool.ruff.lint.flake8-quotes]
|
|
192
|
+
docstring-quotes = "double"
|
|
193
|
+
inline-quotes = "double"
|
|
194
|
+
|
|
195
|
+
[tool.ruff.format]
|
|
196
|
+
quote-style = "double"
|
|
197
|
+
indent-style = "space"
|
|
198
|
+
skip-magic-trailing-comma = false
|
|
199
|
+
line-ending = "lf"
|
|
200
|
+
|
|
201
|
+
[tool.ruff.lint.per-file-ignores]
|
|
202
|
+
# Tests may import fixtures and helpers by name from a sibling module, which reads as
|
|
203
|
+
# an unused import to pyflakes. Every project exempts something here; this is the one
|
|
204
|
+
# thing ours needs now that annotations, docstrings and naming are not selected at all.
|
|
205
|
+
"**/tests/**/*.py" = [
|
|
206
|
+
"PT011", # broad pytest.raises without `match` — fine for the SDK errors we re-raise
|
|
207
|
+
]
|
|
208
|
+
|
|
209
|
+
# --- Pytest --------------------------------------------------------------
|
|
210
|
+
[tool.pytest.ini_options]
|
|
211
|
+
minversion = "7.0"
|
|
212
|
+
testpaths = ["tests"]
|
|
213
|
+
# The shared libraries in `packages/` are imported by name, not installed: the
|
|
214
|
+
# distribution ships no packages, so pytest is what puts them on the path.
|
|
215
|
+
|
|
216
|
+
# "." puts the repository root on the path so the tests can import `generator`, the code
|
|
217
|
+
# that assembles a project. The instruction-file tests import its join rather than
|
|
218
|
+
# reimplementing it, so there is one definition of what a customer receives.
|
|
219
|
+
# "cli/src" puts the installer on the path: it owns the manifest reader, because that is
|
|
220
|
+
# the copy that ships, and `generator` reads the manifest through it.
|
|
221
|
+
pythonpath = ["packages", ".", "cli/src"]
|
|
222
|
+
python_files = ["test_*.py"]
|
|
223
|
+
python_functions = ["test_*"]
|
|
224
|
+
addopts = "-ra"
|
|
225
|
+
# Markers say what a test needs, so a lane deselects what it cannot run instead of the
|
|
226
|
+
# test skipping itself from the inside. Nothing here skips on a missing licence or wheel:
|
|
227
|
+
# a lane that selects these and cannot satisfy them must go red, not quietly green.
|
|
228
|
+
markers = [
|
|
229
|
+
"sdk: needs the licensed cadmould wheel installed (no licence session).",
|
|
230
|
+
"licence: needs a usable cadmould licence session (HASP or cloud account).",
|
|
231
|
+
"cloud: hits the live cloud API; needs a licence carrying the LICENCE_API entitlement.",
|
|
232
|
+
]
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Working with Cadmould
|
|
2
|
+
|
|
3
|
+
Rules that hold for every Cadmould workflow. The section after this one describes the
|
|
4
|
+
workflow in this folder.
|
|
5
|
+
|
|
6
|
+
## Temperatures cross a unit boundary, and getting it wrong is silent
|
|
7
|
+
|
|
8
|
+
| Where | Unit |
|
|
9
|
+
|---|---|
|
|
10
|
+
| Cloud API (`POST /simulations/filling`, `create_filling_simulation`) | **K** |
|
|
11
|
+
| `.plb` material card (`ProcessTemperatures`, `no_flow_temp`) | **K** |
|
|
12
|
+
| SDK deck builder (`with_material(melt_temp=…)`, `ConstantWallTemp`) | **°C** |
|
|
13
|
+
| `/input` group written for the viewer | **°C** |
|
|
14
|
+
|
|
15
|
+
Both units appear inside the SDK itself, so a value read from a material card and passed
|
|
16
|
+
straight to the deck builder is wrong by 273.15 and still builds a valid-looking deck.
|
|
17
|
+
Engineers will say Celsius; the wire wants Kelvin. Convert explicitly at every crossing and
|
|
18
|
+
range-check rather than coercing — 513 offered as °C is an error, not a warning.
|
|
19
|
+
|
|
20
|
+
## Runs are deterministic, so never repeat one
|
|
21
|
+
|
|
22
|
+
An identical configuration returns an identical result. Re-running for confidence or
|
|
23
|
+
averaging adds nothing, replicates carry zero information, and there are no error bars to
|
|
24
|
+
be had from repeats. Spend every run on a new configuration; get robustness from coverage.
|
|
25
|
+
|
|
26
|
+
A **failed** run produced nothing, so that one should be re-run.
|
|
27
|
+
|
|
28
|
+
Do not be conservative with the number of simulations. Run as many as the analysis genuinely
|
|
29
|
+
needs, and prefer breadth over caution.
|
|
30
|
+
|
|
31
|
+
## A gate must sit on a real geometry node
|
|
32
|
+
|
|
33
|
+
Gate positions are node positions from the meshed geometry. They cannot be invented, and
|
|
34
|
+
`0, 0, 0` is not one. Nothing the platform returns will give you node coordinates, so take
|
|
35
|
+
them from the mesh you built.
|
|
36
|
+
|
|
37
|
+
## One licence session, never nested
|
|
38
|
+
|
|
39
|
+
`cadmould.cloud` needs an active session carrying the API entitlement — including
|
|
40
|
+
`set_base_url`, not only the calls that follow it. Open one session and do everything inside
|
|
41
|
+
it: the base URL, every cloud call, and the local meshing.
|
|
42
|
+
|
|
43
|
+
A nested session releases the licence when its inner block exits, leaving later calls
|
|
44
|
+
unlicensed. If a meshing helper opens its own session, have it skip that when the caller
|
|
45
|
+
already holds one.
|
|
46
|
+
|
|
47
|
+
Outside a session you get `LicenceError: Cadmould API licence (LICENCE_API) required` (a
|
|
48
|
+
`RuntimeError`). Inside one, the same error means the licence sign-in failed (see below) or an
|
|
49
|
+
inner session released it. A licence without SDK access
|
|
50
|
+
fails at the session itself, with `Cadmould licence does not include SDK access.`: that is a
|
|
51
|
+
provisioning problem, not a code one.
|
|
52
|
+
|
|
53
|
+
## Three separate sign-ins, and they fix different things
|
|
54
|
+
|
|
55
|
+
`cadmould-sdk-auth` configures the package index so the licensed wheel installs. Opening a
|
|
56
|
+
licence session signs in to the licence in the browser, after checking the Thales Sentinel
|
|
57
|
+
run-time on this machine.
|
|
58
|
+
A bearer token authorises *running* simulations. Conflating them is the usual setup failure.
|
|
59
|
+
|
|
60
|
+
A failed licence sign-in does not raise. It prints `License init failed: <reason>` (or
|
|
61
|
+
`License acquisition failed.`) to the terminal and carries on, so a later `LICENCE_API required`
|
|
62
|
+
is its symptom: find that first line before debugging the call that raised.
|
|
63
|
+
|
|
64
|
+
When a cloud call fails on auth, do a clean re-login before debugging anything else. Tokens
|
|
65
|
+
go stale in ways that still look valid — a plain `401`, a missing-claim error, or an odd
|
|
66
|
+
audience error — and a fresh login clears most of them:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
python -m cadmould_cloud.auth --logout
|
|
70
|
+
python -m cadmould_cloud.auth --print-token --force
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Two commands, not one: `--logout` returns before it fetches anything.
|
|
74
|
+
|
|
75
|
+
## Reading a result without fooling yourself
|
|
76
|
+
|
|
77
|
+
- **A node has arrived when `Degree_of_filling` crosses 0.5.** Keying off `isfinite` makes
|
|
78
|
+
every node arrive at t=0.
|
|
79
|
+
- **`Pressure` carries a `unit` attribute** — Pa in current files, bar in older ones. Read it.
|
|
80
|
+
- **Shear can be `+inf` at a gate node.** Reduce over finite values only, or the metric is swamped.
|
|
81
|
+
- **Field arrays are float16**, so sub-Kelvin steps in temperature are storage quantisation
|
|
82
|
+
rather than physics.
|
|
83
|
+
- **The result geometry is re-centred to the origin** while the gate you sent stays in the
|
|
84
|
+
part frame. Field metrics are unaffected; anything positional needs the shift.
|
|
85
|
+
- **Do not trust a zero in the result summary.** Read the field.
|
|
86
|
+
|
|
87
|
+
## One platform address
|
|
88
|
+
|
|
89
|
+
`https://api.simcon.ai/api/v1`. There is no environment switch and no second address.
|
|
90
|
+
|
|
91
|
+
## Organising a study
|
|
92
|
+
|
|
93
|
+
Work is modelled as a **project** — one per mould that will be built — holding **groups** of
|
|
94
|
+
simulations, with a **decision log** kept as project notes recording why each choice was made.
|
|
95
|
+
That surface is REST only; the SDK does not wrap it.
|
|
96
|
+
|
|
97
|
+
If the task will take more than about five simulations, ask whether to organise it that way
|
|
98
|
+
before starting. For a quick one-off, just run.
|
|
99
|
+
|
|
100
|
+
Current guidance for assistants lives at <https://agents.simcon.ai/start.md>. Instructions in
|
|
101
|
+
this project always win over anything there.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# What this study 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 meshed geometry and results.
|
|
4
|
+
#
|
|
5
|
+
# cache/ is ours: the meshed .cfex and the per-part study state. Safe to delete - it costs
|
|
6
|
+
# a re-mesh and a re-upload, never a wrong answer.
|
|
7
|
+
# output/ is yours: the scored results of each phase.
|
|
8
|
+
cache/
|
|
9
|
+
output/
|
|
10
|
+
|
|
11
|
+
.venv/
|
|
12
|
+
__pycache__/
|
|
13
|
+
*.pyc
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
|
|
16
|
+
# never commit credentials
|
|
17
|
+
*token*.json
|
|
18
|
+
.env
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Gate study — how to drive this template
|
|
2
|
+
|
|
3
|
+
A full gating decision for one part, run as four phases: how many gates, where they go, what
|
|
4
|
+
process settings suit them, and a validation pass. Each phase is a cloud group under one
|
|
5
|
+
project, so the study reads as a record rather than a pile of runs.
|
|
6
|
+
|
|
7
|
+
The method is in [`GATING_STUDY_PLAYBOOK.md`](GATING_STUDY_PLAYBOOK.md). Read it before
|
|
8
|
+
changing what the study measures or pointing it at an unusual part.
|
|
9
|
+
|
|
10
|
+
## What to run
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
python main.py group1 # gate count: 1 vs 2 vs 3 vs 4
|
|
14
|
+
python main.py group2 # placement for the count you chose
|
|
15
|
+
python main.py group3 # process and pressure
|
|
16
|
+
python main.py group4 # validation of the final design
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Add `--part path/to/your.stl` to study your own geometry; no code edit is needed. The part is
|
|
20
|
+
meshed and uploaded once and the ids are cached, so later phases reuse them.
|
|
21
|
+
|
|
22
|
+
## What is in this folder
|
|
23
|
+
|
|
24
|
+
- `main.py` is what you run; `pipeline.py` is the module it drives.
|
|
25
|
+
- `cadmould_cloud/`, `cadmould_geometry/` and `cadmould_scoring/` arrive as packages and are
|
|
26
|
+
imported by name.
|
|
27
|
+
- `sample/` holds the default geometry, and it is ours.
|
|
28
|
+
- `output/` is yours — scored results. `cache/` is ours — the mesh and the study's state.
|
|
29
|
+
Both are created on demand and both are safe to delete; only the cache costs time.
|
|
30
|
+
|
|
31
|
+
## Things to get right here
|
|
32
|
+
|
|
33
|
+
**Confirm the gate count with the engineer rather than deciding it alone.** It is the one
|
|
34
|
+
genuinely subjective fork in the study, and the phases after it all rest on it. Everything
|
|
35
|
+
else the scoring can settle.
|
|
36
|
+
|
|
37
|
+
**Run the phases in order.** Each writes what the next reads. Jumping to `group3` without a
|
|
38
|
+
placement decision scores runs against a design nobody chose.
|
|
39
|
+
|
|
40
|
+
**Weld lines are a placement outcome, not a pass/fail.** Move them somewhere that will not be
|
|
41
|
+
seen rather than trying to eliminate them; that judgement needs the engineer.
|
|
42
|
+
|
|
43
|
+
**A cached study is keyed on the part's contents, not its filename.** Re-export the part and
|
|
44
|
+
it is a different study, deliberately — the mesh and the decisions on file describe the
|
|
45
|
+
previous revision. If a phase says there is no study on file for a part you have already run,
|
|
46
|
+
the part changed.
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Gating-study playbook — how to run an early-stage gate/process study
|
|
2
|
+
|
|
3
|
+
How to drive the cloud AI solver through the early gating decisions for a part, scoring each run
|
|
4
|
+
for filling pressure, fill evenness and weld lines. It ships pointed at `simple_plate.stl` as a
|
|
5
|
+
neutral sample part; the method and tooling generalise to any part.
|
|
6
|
+
|
|
7
|
+
> TL;DR: mesh the STL with the `cadmould` SDK → upload once to the cloud → run batches of
|
|
8
|
+
> gate/process configs through the filling endpoint → score each result for pressure /
|
|
9
|
+
> fill-evenness / weld lines → decide in four phases (gate **count** → **placement** →
|
|
10
|
+
> **process** → **validation**). Tooling: `pipeline.py`, `metrics.py`, `main.py`.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## 0. Mental model
|
|
15
|
+
|
|
16
|
+
Early-stage gating answers, in order:
|
|
17
|
+
|
|
18
|
+
1. **How many gates?** Fewer = higher pressure but fewer/cleaner weld lines; more = lower
|
|
19
|
+
pressure but a weld line between every pair of gates.
|
|
20
|
+
2. **Where do they go?** Position sets flow-length balance (→ even fill + min pressure) and
|
|
21
|
+
*where the weld lines land* (push them to hidden areas).
|
|
22
|
+
3. **What process?** Flow rate (and melt/wall temp) set the pressure/shear/cycle-time window.
|
|
23
|
+
4. **Is it trustworthy?** Determinism, resolution, sanity vs the numerical solver.
|
|
24
|
+
|
|
25
|
+
The levers and their effects are in the **physics cheat-sheet** (§6).
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 1. Environment
|
|
30
|
+
|
|
31
|
+
- **venv** with `numpy, h5py, scipy, trimesh, httpx`. No graphics stack: STL reading is
|
|
32
|
+
trimesh (`cadmould_geometry.stl`) and weld-detection kNN is a scipy KD-tree
|
|
33
|
+
(`metrics.knn_indices`).
|
|
34
|
+
- **cadmould SDK** (licensed; install via `cadmould-sdk-auth` — see
|
|
35
|
+
[`README.md`](README.md)) — used for *local meshing* only; the licence
|
|
36
|
+
is cached (`Session.user_based()`, ~5 s). Meshing/IO live under `cadmould.mesh` /
|
|
37
|
+
`cadmould.mesh.io` / `cadmould.tools`. The `cadmould.cloud` SDK wraps geometry, materials and
|
|
38
|
+
simulations but **not** project/group/decision-log management, so this study drives the cloud
|
|
39
|
+
over the **REST API** via `cadmould_cloud.client::PlatformAPI`.
|
|
40
|
+
- **Cloud auth**: a bearer token for the REST API. `CLOUD_SOLVER_TOKEN` is an optional
|
|
41
|
+
override; with it unset the study resolves one from the token cache, refreshes it if it has
|
|
42
|
+
expired, and otherwise opens the browser sign-in — see
|
|
43
|
+
[`README.md`](README.md). Base URL is a constant in `pipeline.py`
|
|
44
|
+
(override with `CLOUD_BASE_URL`).
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 2. The reusable tooling
|
|
49
|
+
|
|
50
|
+
| File | What it does |
|
|
51
|
+
|---|---|
|
|
52
|
+
| `pipeline.py` | `Study` = one cloud project; meshes+uploads **once**, runs grouped batches concurrently with retry, downloads + scores. |
|
|
53
|
+
| `cadmould_geometry.mesh` | Shared, in `packages/`. Mesh STL→`.cfex`, **parse cfex node coords**, snap gates to real nodes, gate-line layouts. |
|
|
54
|
+
| `cadmould_scoring.metrics` | Shared, in `packages/`. From a result HDF5: peak **pressure** (bar), max **shear**, **fill %**, **fill evenness** (`tail`), **weld-line detection** + clustering. numpy/h5py/scipy only — no graphics stack. |
|
|
55
|
+
| `main.py` | Driver: `group1` (count) / `group2` (placement) / `group3` (process) / `group4` (validation). Caches the geometry id + decisions in `cache/<part>.study_state.json`. |
|
|
56
|
+
|
|
57
|
+
Run: `python main.py group1` (then `group2`, …). State persists between
|
|
58
|
+
phases, so the part is meshed + uploaded once.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 3. The workflow
|
|
63
|
+
|
|
64
|
+
1. **Inspect the geometry first** (bbox, volume, wall thickness, watertight?, holes?, long axis,
|
|
65
|
+
taper). This *predicts* the gating answer before any simulation — for `simple_plate` the 150 mm
|
|
66
|
+
length / 1.5 mm wall (L/t ≈ 100, under PP's ~200) already says "one gate is feasible." A
|
|
67
|
+
quick trimesh script does it (no cloud, no licence) — the kit installs no graphics stack,
|
|
68
|
+
and `cadmould_geometry.stl` is the reader every template uses.
|
|
69
|
+
2. **Validate the metrics offline first**, against an existing result file, before spending cloud
|
|
70
|
+
runs — cloud runs are slow and rate-limited, so don't debug metrics on live runs.
|
|
71
|
+
3. **Group 1 — gate count** at a fixed nominal process (1/2/3/4 gates). Also confirms multi-gate
|
|
72
|
+
is respected and that the weld detector behaves on *this* part.
|
|
73
|
+
4. **Decide the count.** Trade pressure (is it even a constraint?) against weld count/location —
|
|
74
|
+
a genuine fork worth confirming with the user.
|
|
75
|
+
5. **Group 2 — placement** for the chosen count: sweep position, find the flow-balanced point
|
|
76
|
+
(lowest `tail`, lowest pressure), check where welds land. A good place to run a **determinism
|
|
77
|
+
check** (repeat one identical config a few times).
|
|
78
|
+
6. **Group 3 — process**: flow-rate sweep at the chosen gate(s). Map pressure + shear + fill
|
|
79
|
+
time; pick the fastest fill that keeps pressure & shear comfortable.
|
|
80
|
+
7. **Group 4 — validation**: resolution check (e.g. 50 vs 64 timesteps) and, when available, a
|
|
81
|
+
numerical cross-check (§5.5). Confirm the headline metrics are stable.
|
|
82
|
+
8. **The write-up.** Hand the scored results and the `manifest.json` to your assistant and ask
|
|
83
|
+
for the summary you need. The kit produces the numbers, not the document.
|
|
84
|
+
|
|
85
|
+
Keep each phase its own **cloud group** so the run list stays legible.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 4. Metrics (`metrics.py`)
|
|
90
|
+
|
|
91
|
+
- **`max_pressure_bar`** — peak per-node `Pressure` over all steps, in **bar** (reads the stored
|
|
92
|
+
unit). Use this, not the API's `FillingResponse.summary` pressure (not populated).
|
|
93
|
+
- **`fill_time(f)`** → per-node first-arrival time of the front (basis for everything below).
|
|
94
|
+
- **fill evenness `tail_fraction`** — share of total fill time spent filling the last 10 %.
|
|
95
|
+
~0.1 = balanced; large = a region lags (imbalance / air-trap risk). `last_filled_region`
|
|
96
|
+
tells you *where* it finishes (= where to vent).
|
|
97
|
+
- **weld lines** — `detect_welds`: convergence of the **flow-direction field** (gradient of
|
|
98
|
+
fill-time). A weld node = neighbours' flow vectors point *into* it from opposite sides AND the
|
|
99
|
+
two incoming fronts are near head-on. Clustered into lines; `cluster_member_mask` keeps only
|
|
100
|
+
real lines (≥4 connected nodes). Each `WeldCluster` has an `axis_pos` (0..1 along the long
|
|
101
|
+
axis), so you can say "weld at mid-length" vs "at the end."
|
|
102
|
+
- **`max_shear_rate`** — peak shear rate [1/s] over the fill; the real limiter at high flow rate.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## 5. Things to know
|
|
107
|
+
|
|
108
|
+
### 5.1 Auth
|
|
109
|
+
|
|
110
|
+
Cloud REST calls need a bearer token, resolved in that order; a `401` means it is missing or
|
|
111
|
+
expired — set a fresh one. (Install-time SDK auth is the separate `cadmould-sdk-auth` login.)
|
|
112
|
+
|
|
113
|
+
### 5.2 The result file
|
|
114
|
+
|
|
115
|
+
- `Degree_of_filling` is a per-node 0→1 front: 0 before the front arrives, ramps to 1 once
|
|
116
|
+
filled. A node is "filled" once it crosses ~0.5 (this is what `fill_time` keys off).
|
|
117
|
+
- Read `Pressure` via `res.pressure_series_bar()` / `metrics.max_pressure_bar` (bar) and shear
|
|
118
|
+
via `res.shear_rate(step)` (1/s) — both read the stored unit so you don't hard-code it.
|
|
119
|
+
- A result carries the **primary fields only** — no `/input` (process settings) or injection
|
|
120
|
+
curve. The result loader needs the gate/process settings to place the gate marker, so
|
|
121
|
+
inject an `/input` group from the values you submitted (`pipeline._augment_for_viewer`).
|
|
122
|
+
- The result is on the solver's **remeshed** geometry, **re-centred to the origin** — not your
|
|
123
|
+
STL's vertices, and translated from your part's coordinates. So a gate marker from `/input`
|
|
124
|
+
(your part frame) must be shifted onto the result frame before it's drawn (the viewer's
|
|
125
|
+
`align_shift` does this), or just placed at the earliest-filled node. Field metrics are
|
|
126
|
+
unaffected — they live entirely in the result's own frame.
|
|
127
|
+
|
|
128
|
+
### 5.3 Weld detection
|
|
129
|
+
|
|
130
|
+
The detector is the convergence of the flow-direction field, gated by a head-on meeting-angle
|
|
131
|
+
check. Two simpler ideas **don't** work and are worth knowing why: (a) "two earlier neighbours on
|
|
132
|
+
opposite sides arriving simultaneously" fires on ordinary flow (two points on the same advancing
|
|
133
|
+
front arc look opposed); (b) "node is a local terminus" labels most nodes on a fine mesh, where
|
|
134
|
+
neighbours fill barely a step apart. **Calibration check:** a single gate should give ~0 interior
|
|
135
|
+
welds (only a tiny one where the front wraps to the far end); two gates should give one line at
|
|
136
|
+
their midpoint. The midsurface mesh has an open rim where flow simply ends and also "converges" —
|
|
137
|
+
those show up as isolated specks and are filtered out by keeping only clusters of ≥4 nodes.
|
|
138
|
+
|
|
139
|
+
### 5.4 Cloud endpoint
|
|
140
|
+
|
|
141
|
+
- The AI filling call is **synchronous** (~9 s warm) and **sheds load under concurrency**
|
|
142
|
+
(5xx). Run **low concurrency** (`max_workers ≈ 2`) with **retry + backoff** (in
|
|
143
|
+
`_filling_with_retry`); if requests time out, the model is cold — one request warms it.
|
|
144
|
+
- The AI model is **deterministic**: an identical request gives an identical result, so rank
|
|
145
|
+
configs directly — no need to average repeats.
|
|
146
|
+
- The filling endpoint serves the AI solver; the numerical solver is a separate async flow (§5.5).
|
|
147
|
+
|
|
148
|
+
### 5.5 Numerical (physics) cross-check
|
|
149
|
+
|
|
150
|
+
The numerical solver runs on a Cadmould **`.rm1`** input deck (not the `.cfex`, not the AI
|
|
151
|
+
filling request) via a separate **async** flow. Build the rm1 with the SDK:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from cadmould import io
|
|
155
|
+
from cadmould.domain import SimulationConfig, GatePoints, GatePoint, ConstantWallTemp
|
|
156
|
+
from cadmould.material.io import PlbReader
|
|
157
|
+
mat = PlbReader().load(<plb path>) # a material .plb
|
|
158
|
+
cfg = (SimulationConfig.Builder([meshed_mesh]) # parts = list of cadmould.mesh.Mesh
|
|
159
|
+
.with_material(mat, melt_temp=240.0) # °C
|
|
160
|
+
.with_injection(GatePoints([GatePoint(*gate_mm)]))
|
|
161
|
+
.with_wall_temperature(ConstantWallTemp(40.0)) # mould °C
|
|
162
|
+
.build())
|
|
163
|
+
io.Rm1Writer().save(cfg, "part.rm1")
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Then submit async: `POST /api/v1/simulations` `{file_name, simulation_type:"FILL", rm1_file_name}`
|
|
167
|
+
→ PUT the bytes → `POST /simulations/{id}/submit` (`tier` 1..5) → poll `GET /simulations/{id}` →
|
|
168
|
+
`GET /simulations/{id}/downloads`. **Requires a material `.plb`** for `with_material` (the cloud
|
|
169
|
+
catalogue exposes materials by id, not as a downloadable `.plb`); supply one to enable this path.
|
|
170
|
+
|
|
171
|
+
### 5.6 Placing custom gates
|
|
172
|
+
|
|
173
|
+
- The AI surrogate needs each gate to be a **real mesh node**. `run_filling` takes
|
|
174
|
+
`gate_positions_mm` as a list (multi-gate works).
|
|
175
|
+
- The SDK's `Mesh` / `MeshArray` expose no coordinate getters, so to place gates yourself
|
|
176
|
+
**parse the written `.cfex`** (ASCII `#NODDAT,N` block: `index,x,y,z` per node —
|
|
177
|
+
`cadmould_geometry.mesh.parse_cfex_nodes`) and snap your target to the nearest node.
|
|
178
|
+
- `cadmould.tools.suggest_gates` returns a single suggested gate (it doesn't size the count).
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 6. Physics cheat-sheet (how to read results)
|
|
183
|
+
|
|
184
|
+
- **Pressure ∝ longest flow path**, super-linearly → fewer gates / off-centre placement raise it
|
|
185
|
+
steeply (off-centre placement can easily double the peak versus a centred gate). Centre a single gate to minimise
|
|
186
|
+
it. For PP, a couple hundred bar cavity pressure is comfortable; machines do far more.
|
|
187
|
+
- **Weld lines land between adjacent gates** (≈ midpoints) and wherever a front wraps and meets
|
|
188
|
+
itself (a single gate on a long part → welds at the two **ends**). To hide a weld, position
|
|
189
|
+
gates so their midpoint sits over a hidden feature (end, flange, step).
|
|
190
|
+
- **`flow_rate_cm3_s` is the TOTAL** volumetric rate (fill time = volume/flow, independent of
|
|
191
|
+
gate count).
|
|
192
|
+
- **Even fill** = both extremities finish together → minimise `tail`; for a single gate on a
|
|
193
|
+
tapered part the balance point shifts slightly toward the bigger end.
|
|
194
|
+
- **Shear rate rises strongly with flow** and usually caps the flow rate before pressure does.
|
|
195
|
+
- Last-to-fill region = **vent location**.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 7. Adapting to a new part
|
|
200
|
+
|
|
201
|
+
1. Pass your part on the command line: `python main.py group1 --part path/to/newpart.stl`. The
|
|
202
|
+
cloud project is named after it and its cache entries carry a fingerprint of its contents,
|
|
203
|
+
so re-exporting the same part re-meshes and re-uploads on its own. To force that by hand,
|
|
204
|
+
delete only that part's files — `cache/<part>-*` — and leave the other parts' alone.
|
|
205
|
+
2. Re-inspect the geometry (§3.1); the pipeline auto-picks the long axis from the bounding box.
|
|
206
|
+
3. Run `group1..4`; revisit the gate-count fork with the user.
|
|
207
|
+
4. The weld-detector thresholds (`conv_min=0.45`, `min_angle_deg=120`) are tuned for this mesh
|
|
208
|
+
density — **re-validate on the new part's 1-gate vs 2-gate runs** (single gate ≈ no interior
|
|
209
|
+
weld; 2 gates ≈ one line at the midpoint) and adjust if needed.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 8. Limitations
|
|
214
|
+
|
|
215
|
+
- AI surrogate, one prediction per config. A numerical cross-check needs a material `.plb` (§5.5).
|
|
216
|
+
- The weld detector finds head-on collisions well; the cluster threshold is empirical.
|
|
217
|
+
- **"Visible" vs "hidden" is judged geometrically** (ends/edges = hidden) — confirm against the
|
|
218
|
+
part's actual Class-A surface definition.
|
|
219
|
+
- 50–64 timesteps is the working range for the filling call.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# The initial prompt
|
|
2
|
+
|
|
3
|
+
The gate-study pipeline here is driven by a prompt like the one below — a good template for
|
|
4
|
+
kicking off a gating study: state the goal and the constraints, and let the agent drive the cloud
|
|
5
|
+
solver and make the decisions. (Point the study at your own part with `--part path/to/part.stl`;
|
|
6
|
+
the sample one under `sample/` is only a default.)
|
|
7
|
+
|
|
8
|
+
> I have a new part to study. I want to use python wheels and
|
|
9
|
+
> simcon's cloud functionality to go through the typical early stage decisions in designing
|
|
10
|
+
> injection molded parts. Place the necessary number of gates, move them to locations that
|
|
11
|
+
> ensure that the part is filled evenly with an acceptable filling-pressure. Ideally, weldlines
|
|
12
|
+
> (so areas where flow fronts meet) are prevented or at least moved to areas where they won't be
|
|
13
|
+
> visibly noticeable. Do as many simulations as necessary. Validate if you feel the need to.
|
|
14
|
+
> Create a new Project for the part, group simulations into logical groups so I won't be
|
|
15
|
+
> overwhelmed by the number of simulations.
|
|
16
|
+
|
|
17
|
+
## How the harness turns that into a study
|
|
18
|
+
|
|
19
|
+
It meshes and uploads the part **once**, then runs the cloud AI solver in four logical groups —
|
|
20
|
+
**gate count → gate placement → process window → validation** — scoring each run for filling
|
|
21
|
+
pressure, fill evenness and weld lines, and deciding between groups. The method, the metrics, and
|
|
22
|
+
every gotcha are in
|
|
23
|
+
[`GATING_STUDY_PLAYBOOK.md`](GATING_STUDY_PLAYBOOK.md).
|
|
24
|
+
|
|
25
|
+
Tip: confirm the one genuinely subjective fork (gate count) with the user mid-study rather than
|
|
26
|
+
guessing — a good pattern.
|