Files
OneCAD-Simulation/docs/meshing/skill-results.md
T
jyvikoandClaude Opus 5.5 417c0c8897 mesh: the tet objective sees needles; no tet below scaled Jacobian 0.3 on the skill's tet parts
The improvement objective was the smallest dihedral sine, which misses
needles: every dihedral angle fine while a corner is nearly flat, so
the corpus meshes had scaled Jacobians down to 0.01-0.07. The objective
is now the smaller of the dihedral sine and the scaled Jacobian at the
worst corner (the measure analysts check, Knupp 2001), weighted so a
Jacobian of 0.3 (the skill's limit) counts as a 30 degree dihedral
angle (the schedule's target): the Jacobian decides only near that
limit. The existing edge removal, multi-face removal, smoothing and
insertion then remove the needles.

Skill tet10 min SJ: sphere-on-plate 0.092 -> 0.335, filleted-bracket
0.021 -> 0.318 (both pass, nothing marked). Default-size tet10:
thin-ribs 0.240, shallow-groove 0.321, rounded-box 0.311.

The strong-relaxation test relaxes below 0.45: nothing is left below
0.3. Literature note in docs/meshing/literature.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-17 00:51:20 -04:00

17 KiB
Raw Blame History

The meshing skill on the corpus and the samples

Generated by cargo xtask skill-results; do not edit. Each part is meshed by following the meshing skill with today's commands, headless, as an agent over MCP would (crates/testkit/src/skill.rs): geometry.bodies, geometry.features, mesh.plan and geometry.check at the plan's size, mesh.plan.apply (which meshes one cell of a mirror-symmetric body and mirrors it), and where the plan fails the skill's fallbacks in order, mesh.hex.generate, mesh.hex.project (sphere template) and then mesh.tet.generate (tet10); the cells of a split part are joined with mesh.node.merge; then mesh.quality.mark at the skill's limits (scaled Jacobian ≥ 0.3, edge ratio ≤ 10), mesh.node.relax round each marked element when at most 20 are marked (more is a clustered failure: the blocks are wrong, and relaxing is not the fix), mesh.quality.mark again, mesh.quality and mesh.check.duplicates. Sizes are the plan's (1/25 of the body's diagonal, 2 layers through a shell).

Columns: method is what meshed the part (plan (project|cells|sweep) is the skill's target, anything else a fallback); symmetry the mirror planes mesh.plan.apply used; volume error the mesh's volume against the geometry's; untagged faces B-rep faces no element face is tagged with (a set on them finds nothing); marked the elements failing the limits before and after relaxing, and what relaxing changed; ¹ a tet mesh has no edge ratio: its largest aspect ratio stands in; duplicates coincident nodes and cracks; geometry.check its findings at the size; verdict pass when the minimum scaled Jacobian and the largest edge ratio meet the limits and the volume is within 1 % (pass (fallback) when a fallback meshed it). The section pictures cut each part through the middle of its longest side, marked elements red. Times are wall clock on the machine that ran it.

Results

part method symmetry elements min SJ mean SJ max edge ratio¹ volume error untagged faces marked → after relax duplicates geometry.check time s verdict section
bent-tube plan (sweep) – 22272 (22272 hex8) 0.998 0.998 1.4 -2.8e-3 0 0 (not relaxed) none – 3.7 pass y=37.500
bolted-assembly plan (sweep), mesh.hex.generate (auto) – 6272 (6272 hex8) 0.583 0.939 3.6 2.0e-4 0 0 (not relaxed) 8 coincident, 0 cracks – 3.7 pass x=50.000
cantilever-i-beam plan (sweep) – 61600 (61600 hex8) 1.000 1.000 1.0 0.0e0 0 0 (not relaxed) none – 8.5 pass x=100.000
cross-cylinders none – – – – – – – – – – 27.2 no mesh –
filleted-bracket tet10 – 19991 (19991 tet10) 0.318 0.564 4.1 -6.8e-6 0 0 (not relaxed) none – 15.1 pass (fallback) x=30.000
filleted-bracket-blocks plan (sweep) – 75410 (75410 hex8) 0.704 0.954 3.5 3.7e-5 0 0 (not relaxed) none (after merging 2348 nodes) – 6.9 pass x=30.000
i-beam plan (sweep) – 61600 (61600 hex8) 1.000 1.000 1.0 0.0e0 0 0 (not relaxed) none – 4.5 pass z=100.000
loft-transition plan (sweep) – 2873 (2873 hex8) 0.189 0.959 1.7 -2.1e-3 0 4 → 4 (4 relaxed, 0 undone; min SJ 0.189 → 0.189, max ratio 1.7 → 1.7) none – 0.9 fail (SJ) z=25.000
perforated-plate plan (project) 2 plane(s) 8576 (8576 hex8) 0.707 0.888 3.0 7.7e-4 0 0 (not relaxed) none – 9.5 pass x=60.000
pinhole-block plan (project) 2 plane(s) 40768 (40768 hex8) 0.707 0.984 8.0 8.1e-5 0 0 (not relaxed) none – 25.5 pass y=25.000
rounded-box plan (project) 2 plane(s) 11520 (11520 hex8) 0.717 0.973 4.0 -4.1e-3 0 0 (not relaxed) none – 8.7 pass x=20.000
shallow-groove plan (sweep) – 1960 (1960 hex8) 0.991 0.999 1.1 2.7e-4 0 0 (not relaxed) none – 0.2 pass x=30.000
sharp-wedge plan (sweep) – 1674 (1674 hex8) 0.014 0.301 149.6 2.7e-15 0 1524 (not relaxed) none – 0.2 fail (SJ, ratio) x=40.000
sphere-on-plate tet10 – 25613 (25613 tet10) 0.335 0.607 4.4 -8.8e-5 0 0 (not relaxed) none – 7.7 pass (fallback) y=0.000
spline-vase plan (sweep) – 4536 (4536 hex8) 0.665 0.945 9.9 -6.6e-3 0 0 (not relaxed) none – 2.3 pass z=-35.000
stepped-block plan (cells) – 1416 (1416 hex8) 1.000 1.000 1.3 -4.8e-15 0 0 (not relaxed) none – 1.6 pass x=30.000
thin-ribs plan (sweep) – 301308 (301308 hex8) 0.999 1.000 1.3 -3.4e-12 0 0 (not relaxed) none – 34.7 pass x=50.000
thin-wall-enclosure plan (sweep) – 124512 (124512 hex8) 1.000 1.000 1.0 0.0e0 0 0 (not relaxed) none – 13.5 pass x=40.000
analytic-sphere mesh.hex.project (sphere) – 3400 (3400 hex8) 0.728 0.968 3.3 -1.1e-2 0 0 (not relaxed) none – 8.8 fail (volume) z=0.000
analytic-torus plan (sweep) – 48360 (48360 hex8) 0.837 0.986 2.9 -4.2e-3 0 0 (not relaxed) none – 9.8 pass x=0.000
analytic-cylinder plan (project) – 4347 (4347 hex8) 0.859 0.985 2.4 -4.9e-3 0 0 (not relaxed) none – 7.3 pass z=20.000
analytic-pipe plan (project) – 2244 (2244 hex8) 0.997 0.997 1.3 -3.3e-3 0 0 (not relaxed) none – 3.6 pass z=30.000
analytic-plate-hole plan (project) – 5856 (5856 hex8) 0.937 0.996 3.0 4.3e-5 0 0 (not relaxed) none – 4.7 pass x=100.000
crank-arm plan (project) – 4014 (4014 hex8) 0.578 0.933 5.8 -8.4e-4 0 0 (not relaxed) none 4 short_edge, 2 sliver_face 21.7 pass x=81.000
upright-bracket plan (sweep) – 1364 (1364 hex8) 0.707 0.968 3.1 2.1e-4 0 0 (not relaxed) none – 0.1 pass x=30.000
pi5-base plan (project) 1 plane(s) 29852 (29852 hex8) 0.683 0.969 4.9 -3.0e-3 0 0 (not relaxed) none 8 short_edge, 4 sliver_face 131.2 pass x=56.000
pi5-lid plan (project) – 5130 (5130 hex8) 0.724 0.868 3.9 -2.9e-4 0 0 (not relaxed) none – 10.5 pass x=56.000
cup plan (project) – 1258 (1258 hex8) 0.702 0.929 5.0 -3.5e-3 0 0 (not relaxed) none – 3.0 pass x=5.000
plain-cup mesh.hex.generate (auto) – 2000 (2000 hex8) 0.820 0.995 4.7 -2.3e-3 0 0 (not relaxed) none – 1.3 pass (fallback) x=0.000

Why a part fails

Each earlier method's error, in the order the skill tries them, and for a part that fails the limits the cause read from its numbers and section picture.

  • bolted-assembly (corpus: A base plate with a clamp block component placed twice, once turned 90 degrees: bodies placed by component transforms.):
    • Clamp body: mesh.plan.apply: mesh plan Plan-Clamp_body: the projected layout does not mesh: invalid input: node 3076 at [11.000000000000004, 10.0, 5.0] lies on the edge between nodes 2640 and 2715: new elements must meet the mesh face to face, with the same divisions…
    • Clamp body (Clamp:2): mesh.plan.apply: mesh plan Plan-Clamp_body__Clamp_2_: the projected layout does not mesh: invalid input: node 5884 at [66.42857142857143, 5.000000000000001, 5.0] lies on the edge between nodes 984 and 1059: new elements must meet the mesh face to face, wi…
  • cross-cylinders (corpus: Two orthogonal R10 cylinders joined: equal radii, so the intersection curves cross at two singular points.):
    • Cross: mesh.plan.apply: mesh plan Plan-Cross: the cells ["Cross"] (cuts []) do not mesh all-hex: body Cross: invalid boundary surface: 28 defects; triangles 142 and 254 are oriented inconsistently across edge 0–396 at (-15.488656021315903, 4.577998041166734, 7…
    • Cross: mesh.hex.generate: body Cross: invalid boundary surface: 28 defects; triangles 146 and 258 are oriented inconsistently across edge 0–402 at (-15.488656021315903, 4.577998041166734, 7.853092194999726); triangles 255 and 258 are oriented inconsistently across…
    • Cross: mesh.hex.project (sphere): body Cross: invalid boundary surface: 28 defects; triangles 146 and 258 are oriented inconsistently across edge 0–402 at (-15.488656021315903, 4.577998041166734, 7.853092194999726); triangles 255 and 258 are oriented inconsistently across…
    • Cross: mesh.tet.generate: invalid boundary surface: 28 defects; triangles 76 and 78 are oriented inconsistently across edge 9–230 at (-18.75000000000002, 5.634596901641276, 7.632255089815496); triangles 77 and 78 are oriented inconsistently across edge 9–232 at (-15…
    • no mesh: the boundary tessellation of the joined cylinders is invalid (inconsistent orientation at the two singular points), so every mesher refuses the body.
  • filleted-bracket (corpus: An 8 mm L-bracket with an R6 inside fillet and a hole through each leg: a blend beside holes.):
    • Bracket: mesh.plan.apply: mesh plan Plan-Bracket: the cells ["Bracket"] (cuts []) do not mesh all-hex: body Bracket: not supported yet: no structured hex method fits this body (extrude: cylindrical face 8 is not parallel to the direction; sweep: from face 1: lin…
    • Bracket: mesh.hex.generate: body Bracket: not supported yet: no structured hex method fits this body (extrude: cylindrical face 8 is not parallel to the direction; sweep: from face 1: linking face 6 has 2 boundary loops (periodic or holed linking faces are not swept…
    • Bracket: mesh.hex.project (sphere): body Bracket: meshing failed: 91 of 5104 elements are inverted, twisted or degenerate after projection (certified Jacobian; smallest corner scaled Jacobian -0.760): block 1 cell [3, 3, 0] near (12.519, 11.405, 1.604); block 1 cell [3, 4, …
  • loft-transition (corpus: A 40 mm square lofted to an R15 circle 50 mm above: a ruled free-form surface between unlike sections.):
    • fail (SJ): the lofted sides are swept one to one, and the elements where the section changes shape are skewed (min SJ 0.19). Relaxing the four marked elements did not raise it: the blocks are wrong, not the nodes (§6.3). A loft has no template yet (unmapped).
  • sharp-wedge (corpus: A wedge whose faces meet at under 3 degrees: a sharp edge with a needle-thin cross-section.):
    • fail (SJ, ratio): the wedge's sharp edge is swept as hex, so every element tapers to it (min SJ 0.01, edge ratio 150). A column of wedge6 at the edge (§4) raises the SJ but not the ratio: any element with a corner on a 2.9° edge has sides at least 1/tan 2.9° ≈ 20 times its width there, twice the limit. The edge has to be blunted (defeatured) or the limit waived along it.
  • sphere-on-plate (corpus: A sphere sunk 0.1 mm into a plate: the faces meet at under 6 degrees around a 2 mm circle.):
    • Plate: mesh.plan.apply: mesh plan Plan-Plate: the cells ["Plate"] (cuts []) do not mesh all-hex: body Plate: not supported yet: no structured hex method fits this body (extrude: face 6 is curved across the direction; sweep: from face 0: 6 faces are not on the …
    • Plate: mesh.hex.generate: body Plate: not supported yet: no structured hex method fits this body (extrude: face 6 is curved across the direction; sweep: from face 0: 6 faces are not on the sweep path; from face 5: linking face 11 has 2 boundary loops (periodic or …
    • Plate: mesh.hex.project (sphere): body Plate: meshing failed: the mesh volume 32917.42909007507 is far from the body's 69353.30815403847: the blocks do not cover the part (every outer block face must stand for part of its surface)
  • analytic-sphere (corpus: Sphere r 20: curvature everywhere, no edges.):
    • Sphere: mesh.plan.apply: mesh plan Plan-Sphere: the cells ["Sphere"] (cuts []) do not mesh all-hex: body Sphere: not supported yet: no structured hex method fits this body (extrude: no direction to try; sweep: no planar face to sweep from; revolve: no axis to t…
    • Sphere: mesh.hex.generate: body Sphere: not supported yet: no structured hex method fits this body (extrude: no direction to try; sweep: no planar face to sweep from; revolve: no axis to try; mapped: meshing failed: meshing failed: mesh validity gate: 8 inverted or…
    • fail (volume): no structured method takes a sphere (it has no face to sweep from or axis to revolve about), so the plan does not apply and the fallback's sphere template meshes it at the plan's size (2.45 mm, which keeps a sphere's chords to 0.75 % on paper), 1.1 % short of the volume: the template's elements at the cube's eight corners span more of the sphere than the size. A sphere template in the plan (§3) would size its caps; hex20 (order: 2) closes it too.
  • plain-cup (the cup without its handle (#418)):
    • Cup: mesh.plan.apply: mesh plan Plan-Cup: the projected layout does not mesh: body Cup: meshing failed: the mesh volume 5012.205781249979 is far from the body's 16760.91944296662: the blocks do not cover the part (every outer block face must stand for part o…

Parts

  • bent-tube: corpus: A 10 mm tube with a 1 mm wall, bent through R30: a thin-walled sweep along a line-arc-line path.
  • bolted-assembly: corpus: A base plate with a clamp block component placed twice, once turned 90 degrees: bodies placed by component transforms.
  • cantilever-i-beam: corpus: The 200 mm I-beam of i-beam lying along X with its web upright (Z up): a sweep along a horizontal axis, and the cantilever of the README demo.
  • cross-cylinders: corpus: Two orthogonal R10 cylinders joined: equal radii, so the intersection curves cross at two singular points.
  • filleted-bracket: corpus: An 8 mm L-bracket with an R6 inside fillet and a hole through each leg: a blend beside holes.
  • filleted-bracket-blocks: corpus: The filleted bracket split into 30 cells with SolidCraft's Split Body (three slabs across its width, the corner halved along its diagonal, an O-grid of four cells round each hole) so that every cell is a mapped block: conforming multi-block hex meshing.
  • i-beam: corpus: A 200 mm I-beam with 3 mm flanges and a 2 mm web: a long sweepable prism with thin walls.
  • loft-transition: corpus: A 40 mm square lofted to an R15 circle 50 mm above: a ruled free-form surface between unlike sections.
  • perforated-plate: corpus: A 3 mm plate perforated by a 6 x 4 grid of 6 mm holes: genus 24 in a thin sheet.
  • pinhole-block: corpus: A 50 mm block drilled through by sixteen 0.6 mm pinholes: features 80 times smaller than the part, genus 16.
  • rounded-box: corpus: A 40 x 30 x 20 box with every edge rounded R3: cylinder and sphere blends meeting at the corners.
  • shallow-groove: corpus: A block with a 0.5 mm deep groove cut by an R30 cylinder: groove walls 10 degrees off the top face.
  • sharp-wedge: corpus: A wedge whose faces meet at under 3 degrees: a sharp edge with a needle-thin cross-section.
  • sphere-on-plate: corpus: A sphere sunk 0.1 mm into a plate: the faces meet at under 6 degrees around a 2 mm circle.
  • spline-vase: corpus: A vase revolved from a spline profile: doubly curved faces of varying curvature around a closed axis.
  • stepped-block: corpus: Three stacked blocks with a slot cut through the base: axis-aligned steps for polycube and octree meshers.
  • thin-ribs: corpus: A 4 mm plate carrying five 0.8 mm ribs 20 mm tall: thin walls standing on a thicker base.
  • thin-wall-enclosure: corpus: An 80 x 60 x 40 box shelled to 1 mm walls, open on top: thin walls over a large span.
  • analytic-sphere: corpus: Sphere r 20: curvature everywhere, no edges.
  • analytic-torus: corpus: Torus 30/8: genus 1 with doubly curved faces and no edges.
  • analytic-cylinder: corpus: Cylinder r 10, h 40: the round bar of beam and torsion checks.
  • analytic-pipe: corpus: Thick-walled pipe 20/30, length 60: the Lamé cylinder.
  • analytic-plate-hole: corpus: Plate 200 x 100 x 5 with a 20 mm hole: the Kirsch plate.
  • crank-arm: sample crank-arm: the 170 mm bicycle crank, mirror symmetric across y = 0
  • upright-bracket: samples drop-test, flow-past: the upright L-bracket
  • pi5-base: the Raspberry Pi 5 enclosure's base: a shelled box with fillets and standoffs
  • pi5-lid: the Raspberry Pi 5 enclosure's lid
  • cup: the cup with a handle of #418
  • plain-cup: the cup without its handle (#418)