Files
OneCAD-Simulation/skills/fieldcraft-meshing/SKILL.md
T
jyvikoandClaude Opus 5.5 5db21aba7b ui: geometry.defeature.propose lists the small features with an on/off switch each (#433)
Holes by diameter, fillets by radius, chamfers by distance and bosses by height below
thresholds, or under a geometry.check finding; the reply panel switches each feature
off and on (geometry.defeature) and defeatures the whole proposal.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-16 18:30:45 -04:00

158 lines
10 KiB
Markdown

---
name: fieldcraft-meshing
description: Agentic hex meshing (AHM) in FieldCraft — look at the part, use its symmetry, plan the blocks, mesh, mark and fix the bad elements, and show sections an analyst would accept. Use before any mesh.* command on a part that matters, and whenever a mesh comes back with fans, slivers or a low scaled Jacobian.
---
# Agentic hex meshing (AHM)
Mesh like an analyst: look first, plan the blocks, then call a mesher. A mesh is judged by its
worst elements, not its count. A fast mesh with fans, slivers or collapsed corners is a failed
mesh, even when every element is valid.
The loop: **look → symmetry → plan → inspect the plan → apply → quality + mark → relax → section
pictures → report.** Never skip a step because the last mesh looked fine.
## 1. Look before you mesh
1. `inspect_model` / `geometry.bodies`: bodies, volumes, bounding boxes, faces, holes, fillets.
For a `.solidcraft` design also `geometry.features {"body"}`: how each body was built
(profiles, extrude directions, holes, shells, fillets, patterns, mirrors).
2. `geometry.check {"body", "size"}` at the size you intend (run `mesh.plan` first and take its
`size`): short edges, small and sliver faces,
near faces (gaps, overlaps, walls thinner than the gap). Each finding names its faces and a
point `at`, and is marked in pictures. Defeature or resize before meshing; never mesh over a
finding you have not explained. `geometry.defeature.propose {"body", "below": {"hole_diameter",
"fillet_radius", "chamfer", "boss_height"}, "from_check": true}` lists the holes, fillets,
chamfers and bosses below a size or under a finding; `geometry.defeature {"name", "features"}`
takes them out (the design rebuilt without them), `geometry.defeature.delete` puts them back.
3. Take pictures. Headless: `fieldcraft-cli snapshot script.json --out a.png` with
`--view iso|front|top|…` or `--camera '{"yaw":-45,"pitch":30,"target":[x,y,z],"fit":true}'`,
and `--section x|y|z[=VALUE]`. Over MCP: `screenshot {view | camera: {yaw, pitch, target,
distance | fit}, section}`. Aim `target` at the feature you are judging (a boss, a corner), not
the model's centre. Read every PNG. Name, in words, what the part is.
4. Primary vs secondary features. Primary (walls, bosses, the load path, thin directions, the
sweep direction) set the block topology. Secondary (small fillets, chamfers, logos, small holes
far from the region of interest) fit into it or are defeatured; they never drive it.
## 2. Symmetry first
Test symmetry geometrically (mirror the bounding box and the key faces). `mesh.plan.apply` does it
itself for a projection plan (`symmetry`, default true): it meshes one cell of a body mirror
symmetric across planes through its middle and mirrors it, and lists the planes it used in its
reply's `symmetry`. Read that list. An empty one on a part you know is symmetric (the crank arm
comes back without its y = 0 plane) means the plan meshed it whole: check that the halves came
out alike, or partition and mirror by hand. If the part and its loads are symmetric, mesh one
half or quarter and mirror the mesh: `mesh.mirror {"plane": <datum
plane> | {point, normal}}`. Nodes on the plane are merged, so the result is conforming. Never mesh
a symmetric part whole. If the halves come out unequal (one corner good, its mirror image bad),
keep the good half and mirror it.
`mesh.plan` refuses a partitioned body and its cells today (#473): for a half, mesh the cell with
`mesh.cells` or `mesh.hex.project`, then mirror.
## 3. Plan, then inspect the plan
1. `mesh.plan {"body", "size"?, "layers"?}`: the block plan from the features. Nothing is meshed.
2. Read the plan before applying it:
- `mesher`: `project` (one block topology over the body: O-grid rings round circles, blend
layers along fillets, chamfers and shell walls; for a section at an angle to the axes, such
as a crank arm, an annulus round each boss's hole and a carved grid with a pillow layer to
the outline) is the target; `cells`/`sweep` is the fallback.
- `rings`: centre, radius, frame half-side. Frames should be near square with even margins.
- `cuts`: each with its feature and reason.
- `notes`: why the body did not fit the projection layout.
- `pending` (rings left boxed) and `unmapped` (features with no template: revolves, sweeps,
lofts).
- `size` and `layers` against the thinnest wall (§5).
Fix what is wrong by editing the plan object and applying the edit.
3. `mesh.plan.apply {"plan": <the plan reply's `name`> | edited object}`. The saved name is not
always `Plan-<body>`: names with spaces or punctuation are made safe (`Plan-Clamp_body`). Read `skipped_cuts`, `all_hex`,
`conforming`, `min_scaled_jacobian`, `layout`, `blend_layers`. A skipped cut is a defect to
explain.
4. When the plan does not fit, mesh regions by hand and keep the plan's cuts that work:
`geometry.partition` + `mesh.cells`; `mesh.hex.generate` / `mesh.hex.sweep` / `mesh.hex.mapped`;
`mesh.hex.extrude` for a section carried to a curved or tilted end (`source`, `to_surface`,
`sides`); `mesh.hex.project` for a block topology projected on the part (`template` `sphere` or
`butterfly`, ops `o_grid`, `split`, `extrude`, `connect`; `preview: true` lists block indices).
Tet (`tet10` for stress) only for cells not worth blocking, far from the region of interest.
In that order: `mesh.hex.generate` (it picks extrude, sweep, revolve or mapped), then
`mesh.hex.project` with the template the shape asks for (`sphere` for a ball), then tet10.
Name each failure in the report.
5. Mesh touching bodies one at a time and read the error: `mesh.plan.apply` on a body that
touches one already meshed must meet that mesh face to face, and fails ("must meet the mesh
face to face") when the divisions differ. Plan both with the same size, or mesh the second
with `mesh.hex.generate` and tie them (§4).
Shapes without a timeline (STEP, 3MF) skip `mesh.plan` and go to step 4.
## 4. Block rules
- **No sharp corners.** Every element corner near 90°. Where a block corner is far from 90°, cut
differently or add an O-grid.
- **No skewed, tapered or long thin cells.** Check every cell a cut makes; a wedge, sliver or
strip means the cut is wrong.
- **O-grid round every hole, boss, cylinder and fillet**: a square round the curve and a ring
between, element lines radial, square corners at 45° on the curve. Never fan into a hole or
pinch at a tangency.
- **Never cut on an existing face.** A coincident cut leaves slivers, and one the kernel can only
make by nudging off the plane is refused (`geometry.partition`). Offset the cut one element out
of the feature. Never cut through the axis of a small hole.
- **Parity at corners.** Division counts must close round every block loop. Where a corner comes
out bad and its mirror image is good, change the count by one on the edges leading into it
(`mesh.seed.edge`) first.
- **Pattern a good corner.** When identical features (four corner bosses) mesh unequally, the
good one is the template: mirror it onto the others (`mesh.mirror`) instead of accepting the
worst.
- **Accept a wedge column** where the layout forces one node to absorb a corner: one column of
`wedge6` is better than a column of skewed hex. State it in the report.
- **Keep cuts consistent across touching bodies** so the meshes match, or tie them
(`interaction.tie`).
## 5. Size and walls
- Through a thin wall: at least 2 elements for bending (3 for stress in the wall), 1 only for
pure conduction. Set `layers` in `mesh.plan`, or `mesh.seed.edge` across the wall.
- Matching counts on shared edges: `mesh.seed.edge`.
- Size from the physics: finer at stress gradients, fillets and contact; in explicit, from the
wave length. Refine locally with `mesh.size.set` (faces, bodies, a box or a sphere) rather
than making the whole part fine; `mesh.size.growth` sets how fast it coarsens away.
## 6. Quality, mark, relax
1. `mesh.quality`: all valid; volume equal to the geometry's (a mismatch means missing or orphan
cells, or elements too coarse for the curvature: a 1 mm tube wall swept at the default size
loses 17 %). A tet mesh has no `edge_ratio`: judge it by `aspect_ratio`.
2. `mesh.quality.mark {"limits": {"scaled_jacobian": 0.3, "edge_ratio": 10}}`: failing elements
become the set `quality_marked`, drawn red in pictures, each with `label`, `at`, `failed`.
Acceptance limits:
- scaled Jacobian ≥ 0.3 everywhere, ≥ 0.5 in the region of interest;
- edge ratio and aspect ratio ≤ 10;
- face angles 15°–165°, dihedrals 10°–165° (the defaults).
3. Picture the marked elements (camera `target` at their `at`, a `section` through them).
Clustered marks mean the blocks are wrong: back to §3/§4. Isolated spikes only:
`mesh.node.relax {"around_element": <label>}` for each marked element (by CAD face once #471
lands; sets are for the analysis steps, not for relaxing). Surface nodes
slide on their faces; nothing inverts. Add `"reapply": true` so it follows a remesh. Read the
reply's `before` and `after`: relaxing guards the scaled Jacobian, not the edge ratio, and on
the crank arm's bore corner it raised the region's edge ratio from 10.5 to over 2000. When
`after` is worse on either, `edit.undo` it. Relaxing is the final touch, never a substitute
for a better plan.
4. Mark again until nothing is marked, or every remaining mark has a stated reason.
5. `mesh.check.duplicates`: no cracks or free edges inside a body. Cells of one part meshed one
by one (split bodies) join with `mesh.node.merge`; separate parts that touch are tied, never
merged.
6. Section pictures through every primary feature: fans, pinches, wedges, slivers or zigzag lines
→ back to §3.
7. After solving, refine once and compare the quantity of interest (convergence).
## 7. Report
State: symmetry used, primary features, the plan's mesher, every cut and skipped cut with its
reason, method per region, element counts, min scaled Jacobian, max edge ratio, marked count, what
was relaxed, any wedge column, anything defeatured, and the section pictures. If the plan failed,
name the rule that failed and the next thing you will try. Never silently fall back to a worse
mesh.
What this procedure gives today on every corpus part and sample, and why each failure fails:
docs/meshing/skill-results.md (`cargo xtask skill-results`).