forked from 1b-agent/fieldcraft-upstream
Tet mesh quality: one validity criterion, Delaunay refinement, ODT, Klingner–Shewchuk, tet10
The end-to-end demo met a raw-CDT sliver that the validity gate accepted (exactly positive) and the solver refused. Now: - One validity criterion, `fieldcraft_model::admissible_jacobian` (normalized Jacobian above 1e-12), used by the implicit solver (fem `positive_inverse`), the explicit tet4/hex8 kinematics and the mesh gate, which proves it on the whole element (tet4: the solvers' own Jacobian; curved kinds: a Bernstein floor), so whatever passes the gate passes the solvers. - CDT rounding repaired by flips on the rounded mesh (Diazzi et al. 2023 §5.1) instead of the ±2-ulp nudge. - `fieldcraft-mesh::tet`: a mutable tetrahedral complex whose every change is a checked replacement (positive and admissible tetrahedra, faces matched with opposite orientation) with an exact undo log; edge removal (Klincsek), multi-face removal, Delaunay insertion with boundary faces, edge collapse; a curvature- and thickness-graded size field; constrained Delaunay refinement with encroachment splits; ODT smoothing; the Klingner–Shewchuk schedule; boundary vertices moved onto the exact B-rep surfaces at the end; tet10 with mid-edge nodes on the geometry. - `mesh.tet.generate` gains size, order, quality, quality_target, curvature_angle, grading, max_passes, max_points and reports the CDT's and the mesh's quality; `solve.probe` takes a set and reports its largest von Mises stress. - Oracle cases filleted-bracket-fillet-stress(-coarse): the fillet's peak von Mises stress on tet10 meshes of 2k and 13.5k elements, 213.3 MPa (a four-level study stays within 1.8%); the CDT cases keep the raw tetrahedralization. - Corpus quality columns: all 20 valid parts mesh and pass the gate. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
This commit is contained in:
1 parent
fed27d816d
commit
9469ac0853
53 files changed
+5880
-278
No files matched your search
@@ -1,3 +1,3 @@
|
||||
[
|
||||
{"command": "mesh.tet.generate", "params": {"body": "Cylinder", "tolerance": 0.05}, "id": "tet"}
|
||||
{"command": "mesh.tet.generate", "params": {"body": "Cylinder", "tolerance": 0.05, "quality": false}, "id": "tet"}
|
||||
]
|
||||
@@ -1,3 +1,3 @@
|
||||
[
|
||||
{"command": "mesh.tet.generate", "params": {"body": "Steps", "tolerance": 0.05}, "id": "tet"}
|
||||
{"command": "mesh.tet.generate", "params": {"body": "Steps", "tolerance": 0.05, "quality": false}, "id": "tet"}
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
# Filleted L-bracket: peak stress on the fillet (coarse mesh)
|
||||
|
||||
The corpus part `filleted-bracket` (an 8 mm L-bracket with an R6 inside fillet and a hole through
|
||||
each leg), built with SolidCraft from `design.json`. The foot face `F2:side:l1` is clamped and a
|
||||
2 kN load in +x acts on the top face `F2:side:l5` (steel, E = 210 GPa, ν = 0.3). The leg bends
|
||||
about its root, where the fillet concentrates the stress; beam theory gives about 197 MPa nominal
|
||||
at the root (6FL/(bt²) with L = 42 mm, b = 40 mm, t = 8 mm).
|
||||
|
||||
`mesh.tet.generate` makes a quality tet10 mesh (size 16 mm, 90° per element along curved
|
||||
faces), with the boundary and mid-edge nodes on the exact fillet cylinder. The peak nodal von
|
||||
Mises stress on the fillet over a four-level study (sizes 16, 11.3, 8, 5.66 mm with 90°, 64°,
|
||||
45°, 32°): 213.3, 210.6, 214.3, 213.3 MPa. The coarse and the fine level are the two cases.
|
||||
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"command": "sketch.create",
|
||||
"params": {
|
||||
"plane": "XY",
|
||||
"name": "Profile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "sketch.line",
|
||||
"params": {
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
60,
|
||||
0
|
||||
],
|
||||
[
|
||||
60,
|
||||
8
|
||||
],
|
||||
[
|
||||
8,
|
||||
8
|
||||
],
|
||||
[
|
||||
8,
|
||||
50
|
||||
],
|
||||
[
|
||||
0,
|
||||
50
|
||||
]
|
||||
],
|
||||
"closed": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "sketch.finish",
|
||||
"params": {}
|
||||
},
|
||||
{
|
||||
"command": "solid.extrude",
|
||||
"params": {
|
||||
"distance": 40,
|
||||
"body_name": "Bracket"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "solid.fillet",
|
||||
"params": {
|
||||
"edges": [
|
||||
[
|
||||
8,
|
||||
8,
|
||||
20
|
||||
]
|
||||
],
|
||||
"radius": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "solid.hole",
|
||||
"params": {
|
||||
"position": [
|
||||
40,
|
||||
8,
|
||||
20
|
||||
],
|
||||
"diameter": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "solid.hole",
|
||||
"params": {
|
||||
"position": [
|
||||
8,
|
||||
32,
|
||||
20
|
||||
],
|
||||
"diameter": 8
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"title": "Filleted L-bracket under a side load: the peak von Mises stress on the R6 fillet, coarse tet10 mesh",
|
||||
"kind": "theory",
|
||||
"source": "mesh convergence of the finite element solution (P. J. Roache, Verification and Validation in Computational Science and Engineering, Hermosa, 1998, ch. 5): the bracket has no closed-form stress; the reference is the mesh-independent peak of a four-level study of quadratic tetrahedral meshes refined by √2 in size and in curvature resolution (README.md); equilibrium",
|
||||
"slow": true,
|
||||
"quantities": [
|
||||
{
|
||||
"id": "fillet_peak",
|
||||
"quantity": "largest nodal von Mises stress on the fillet face (MPa)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Load",
|
||||
"set": "fillet"
|
||||
},
|
||||
"pointer": "/max_von_mises/value"
|
||||
},
|
||||
"value": 213.0,
|
||||
"tolerance": {
|
||||
"relative": 0.03
|
||||
},
|
||||
"reason": "the four-level study gives 213.3, 210.6, 214.3, 213.3 MPa (2k to 13.5k elements): the bending stress is converged across the fillet, and the peak nodal value moves only with which of the fillet's tessellation lines (fixed angles, through every level) carries the largest node, by under 2%"
|
||||
},
|
||||
{
|
||||
"id": "reaction",
|
||||
"quantity": "total reaction x (N)",
|
||||
"measure": {
|
||||
"from": "solve",
|
||||
"pointer": "/reaction_total/0"
|
||||
},
|
||||
"value": -2000.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "equilibrium holds to rounding"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"note": "FieldCraft's accepted results for this case, written by `cargo xtask oracle --bless`. A result outside its band fails CI.",
|
||||
"values": {
|
||||
"fillet_peak": {
|
||||
"band": 2.1330697455903942e-7,
|
||||
"value": 213.30697455903942
|
||||
},
|
||||
"reaction": {
|
||||
"band": 2.000000000000858e-6,
|
||||
"value": -2000.0000000008579
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
[
|
||||
{"command": "mesh.tet.generate", "params": {"body": "Bracket", "tolerance": 0.088, "size": 16.0, "curvature_angle": 90.0, "order": "quadratic"}, "id": "tet"},
|
||||
{"command": "model.material.create", "params": {"name": "Steel", "elastic": {"type": "isotropic", "young": 210000, "poisson": 0.3}, "density": 7.85e-09}},
|
||||
{"command": "model.set.create", "params": {"name": "all", "geometry": [{"body": "Bracket"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "foot", "geometry": [{"body": "Bracket", "face": "F2:side:l1"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "top", "geometry": [{"body": "Bracket", "face": "F2:side:l5"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "fillet", "geometry": [{"body": "Bracket", "face": "F3:blend:F2:side:l3|F2:side:l4"}]}},
|
||||
{"command": "model.section.create", "params": {"name": "solid", "set": "all", "material": "Steel", "kind": {"type": "solid"}}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "clamp", "type": "fixed", "target": {"set": "foot"}}},
|
||||
{"command": "model.load.create", "params": {"name": "push", "type": "force", "target": {"set": "top"}, "vector": [2000, 0, 0]}},
|
||||
{"command": "model.step.create", "params": {"name": "Load", "procedure": {"type": "static"}, "boundary_conditions": ["clamp"], "loads": ["push"]}},
|
||||
{"command": "solve.static", "params": {}, "id": "solve"}
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
# Filleted L-bracket: peak stress on the fillet (fine mesh)
|
||||
|
||||
The corpus part `filleted-bracket` (an 8 mm L-bracket with an R6 inside fillet and a hole through
|
||||
each leg), built with SolidCraft from `design.json`. The foot face `F2:side:l1` is clamped and a
|
||||
2 kN load in +x acts on the top face `F2:side:l5` (steel, E = 210 GPa, ν = 0.3). The leg bends
|
||||
about its root, where the fillet concentrates the stress; beam theory gives about 197 MPa nominal
|
||||
at the root (6FL/(bt²) with L = 42 mm, b = 40 mm, t = 8 mm).
|
||||
|
||||
`mesh.tet.generate` makes a quality tet10 mesh (size 5.66 mm, 31.8° per element along curved
|
||||
faces), with the boundary and mid-edge nodes on the exact fillet cylinder. The peak nodal von
|
||||
Mises stress on the fillet over a four-level study (sizes 16, 11.3, 8, 5.66 mm with 90°, 64°,
|
||||
45°, 32°): 213.3, 210.6, 214.3, 213.3 MPa. The coarse and the fine level are the two cases.
|
||||
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"commands": [
|
||||
{
|
||||
"command": "sketch.create",
|
||||
"params": {
|
||||
"plane": "XY",
|
||||
"name": "Profile"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "sketch.line",
|
||||
"params": {
|
||||
"points": [
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
60,
|
||||
0
|
||||
],
|
||||
[
|
||||
60,
|
||||
8
|
||||
],
|
||||
[
|
||||
8,
|
||||
8
|
||||
],
|
||||
[
|
||||
8,
|
||||
50
|
||||
],
|
||||
[
|
||||
0,
|
||||
50
|
||||
]
|
||||
],
|
||||
"closed": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "sketch.finish",
|
||||
"params": {}
|
||||
},
|
||||
{
|
||||
"command": "solid.extrude",
|
||||
"params": {
|
||||
"distance": 40,
|
||||
"body_name": "Bracket"
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "solid.fillet",
|
||||
"params": {
|
||||
"edges": [
|
||||
[
|
||||
8,
|
||||
8,
|
||||
20
|
||||
]
|
||||
],
|
||||
"radius": 6
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "solid.hole",
|
||||
"params": {
|
||||
"position": [
|
||||
40,
|
||||
8,
|
||||
20
|
||||
],
|
||||
"diameter": 8
|
||||
}
|
||||
},
|
||||
{
|
||||
"command": "solid.hole",
|
||||
"params": {
|
||||
"position": [
|
||||
8,
|
||||
32,
|
||||
20
|
||||
],
|
||||
"diameter": 8
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"title": "Filleted L-bracket under a side load: the peak von Mises stress on the R6 fillet, fine tet10 mesh",
|
||||
"kind": "theory",
|
||||
"source": "mesh convergence of the finite element solution (P. J. Roache, Verification and Validation in Computational Science and Engineering, Hermosa, 1998, ch. 5): the bracket has no closed-form stress; the reference is the mesh-independent peak of a four-level study of quadratic tetrahedral meshes refined by √2 in size and in curvature resolution (README.md); equilibrium",
|
||||
"slow": true,
|
||||
"quantities": [
|
||||
{
|
||||
"id": "fillet_peak",
|
||||
"quantity": "largest nodal von Mises stress on the fillet face (MPa)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Load",
|
||||
"set": "fillet"
|
||||
},
|
||||
"pointer": "/max_von_mises/value"
|
||||
},
|
||||
"value": 213.0,
|
||||
"tolerance": {
|
||||
"relative": 0.03
|
||||
},
|
||||
"reason": "the four-level study gives 213.3, 210.6, 214.3, 213.3 MPa (2k to 13.5k elements): the bending stress is converged across the fillet, and the peak nodal value moves only with which of the fillet's tessellation lines (fixed angles, through every level) carries the largest node, by under 2%"
|
||||
},
|
||||
{
|
||||
"id": "reaction",
|
||||
"quantity": "total reaction x (N)",
|
||||
"measure": {
|
||||
"from": "solve",
|
||||
"pointer": "/reaction_total/0"
|
||||
},
|
||||
"value": -2000.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "equilibrium holds to rounding"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"note": "FieldCraft's accepted results for this case, written by `cargo xtask oracle --bless`. A result outside its band fails CI.",
|
||||
"values": {
|
||||
"fillet_peak": {
|
||||
"band": 2.1330693756948646e-7,
|
||||
"value": 213.30693756948645
|
||||
},
|
||||
"reaction": {
|
||||
"band": 2.0000000000001007e-6,
|
||||
"value": -2000.0000000001007
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
[
|
||||
{"command": "mesh.tet.generate", "params": {"body": "Bracket", "tolerance": 0.088, "size": 5.65685424949238, "curvature_angle": 31.819805153394636, "order": "quadratic"}, "id": "tet"},
|
||||
{"command": "model.material.create", "params": {"name": "Steel", "elastic": {"type": "isotropic", "young": 210000, "poisson": 0.3}, "density": 7.85e-09}},
|
||||
{"command": "model.set.create", "params": {"name": "all", "geometry": [{"body": "Bracket"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "foot", "geometry": [{"body": "Bracket", "face": "F2:side:l1"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "top", "geometry": [{"body": "Bracket", "face": "F2:side:l5"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "fillet", "geometry": [{"body": "Bracket", "face": "F3:blend:F2:side:l3|F2:side:l4"}]}},
|
||||
{"command": "model.section.create", "params": {"name": "solid", "set": "all", "material": "Steel", "kind": {"type": "solid"}}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "clamp", "type": "fixed", "target": {"set": "foot"}}},
|
||||
{"command": "model.load.create", "params": {"name": "push", "type": "force", "target": {"set": "top"}, "vector": [2000, 0, 0]}},
|
||||
{"command": "model.step.create", "params": {"name": "Load", "procedure": {"type": "static"}, "boundary_conditions": ["clamp"], "loads": ["push"]}},
|
||||
{"command": "solve.static", "params": {}, "id": "solve"}
|
||||
]
|
||||
Reference in new issue
Block a user