forked from 1b-agent/fieldcraft-upstream
Verification oracle: tests/oracle cases, cargo xtask oracle, fixtures, docs/oracle.md, CI job
The oracle binary (modelcraft-testkit) runs each case's recipe through the command engine, measures its quantities by JSON pointers into step outputs or commands, compares them with the cited references and the frozen fixtures, and writes docs/oracle.md. 20 theory cases (patch tests of every solid element, Timoshenko cantilevers, Lame, Kirsch, beam frequencies, torsion and bending through couplings, explicit waves and impact, CDT invariants), 8 published benchmarks (MacNeal-Harder patch, straight and curved cantilevers, thick cylinder, Scordelis-Lo with solids, NAFEMS LE1, LE10, FV32) and 10 pending cases with citations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
This commit is contained in:
1 parent
a3cb6d749b
commit
6d9452ad84
144 files changed
+5162
-74
No files matched your search
@@ -0,0 +1,6 @@
|
||||
# MacNeal–Harder patch test for solids (hex8 with incompatible modes)
|
||||
|
||||
Our model of the published problem: a unit cube cut into seven hexahedra around an irregular inner
|
||||
hexahedron (inner node coordinates from Fig. 3), E = 10⁶, ν = 0.25, with the linear displacement
|
||||
field of Table 2(c) prescribed at the eight corners. The published solution is the uniform strain
|
||||
10⁻³ with σ_x = σ_y = σ_z = 2000 and τ = 400.
|
||||
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"title": "MacNeal–Harder patch test for solids (hex8 with incompatible modes)",
|
||||
"kind": "benchmark",
|
||||
"source": "MacNeal and Harder, 'A proposed standard set of problems to test finite element accuracy', Finite Elements in Analysis and Design 1 (1985) 3–20: Fig. 3 (p. 6) geometry and inner node locations, Table 2(c) (p. 10) boundary displacements and theoretical solution",
|
||||
"quantities": [
|
||||
{
|
||||
"id": "sxx",
|
||||
"quantity": "σ_xx at inner node 7 (0.788, 0.693, 0.644)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Patch",
|
||||
"at": [
|
||||
[
|
||||
0.788,
|
||||
0.693,
|
||||
0.644
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/0"
|
||||
},
|
||||
"value": 2000.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "syy",
|
||||
"quantity": "σ_yy at inner node 7 (0.788, 0.693, 0.644)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Patch",
|
||||
"at": [
|
||||
[
|
||||
0.788,
|
||||
0.693,
|
||||
0.644
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/1"
|
||||
},
|
||||
"value": 2000.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "szz",
|
||||
"quantity": "σ_zz at inner node 7 (0.788, 0.693, 0.644)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Patch",
|
||||
"at": [
|
||||
[
|
||||
0.788,
|
||||
0.693,
|
||||
0.644
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/2"
|
||||
},
|
||||
"value": 2000.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "txy",
|
||||
"quantity": "τ_xy at inner node 7",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Patch",
|
||||
"at": [
|
||||
[
|
||||
0.788,
|
||||
0.693,
|
||||
0.644
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/3"
|
||||
},
|
||||
"value": 400.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "txz",
|
||||
"quantity": "τ_xz at inner node 7",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Patch",
|
||||
"at": [
|
||||
[
|
||||
0.788,
|
||||
0.693,
|
||||
0.644
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/4"
|
||||
},
|
||||
"value": 400.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "tyz",
|
||||
"quantity": "τ_yz at inner node 7",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Patch",
|
||||
"at": [
|
||||
[
|
||||
0.788,
|
||||
0.693,
|
||||
0.644
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/5"
|
||||
},
|
||||
"value": 400.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "u7",
|
||||
"quantity": "u_x at inner node 7",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Patch",
|
||||
"at": [
|
||||
[
|
||||
0.788,
|
||||
0.693,
|
||||
0.644
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/displacement/0"
|
||||
},
|
||||
"value": 0.0014565000000000001,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"note": "ModelCraft's accepted results for this case, written by `cargo xtask oracle --bless`. A result outside its band fails CI.",
|
||||
"values": {
|
||||
"sxx": {
|
||||
"band": 2.000000000000001e-6,
|
||||
"value": 2000.000000000001
|
||||
},
|
||||
"syy": {
|
||||
"band": 2.000000000000003e-6,
|
||||
"value": 2000.0000000000027
|
||||
},
|
||||
"szz": {
|
||||
"band": 2.000000000000003e-6,
|
||||
"value": 2000.0000000000027
|
||||
},
|
||||
"txy": {
|
||||
"band": 4.00000000000001e-7,
|
||||
"value": 400.00000000000097
|
||||
},
|
||||
"txz": {
|
||||
"band": 4.0000000000000003e-7,
|
||||
"value": 399.99999999999994
|
||||
},
|
||||
"tyz": {
|
||||
"band": 4.0000000000000003e-7,
|
||||
"value": 399.9999999999994
|
||||
},
|
||||
"u7": {
|
||||
"band": 1.4565000000000005e-12,
|
||||
"value": 0.0014565000000000003
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
[
|
||||
{"command": "mesh.node.add", "params": {"label": 1, "xyz": [0, 0, 0]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 2, "xyz": [1, 0, 0]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 3, "xyz": [1, 1, 0]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 4, "xyz": [0, 1, 0]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 5, "xyz": [0, 0, 1]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 6, "xyz": [1, 0, 1]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 7, "xyz": [1, 1, 1]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 8, "xyz": [0, 1, 1]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 9, "xyz": [0.249, 0.342, 0.192]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 10, "xyz": [0.826, 0.288, 0.288]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 11, "xyz": [0.85, 0.649, 0.263]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 12, "xyz": [0.273, 0.75, 0.23]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 13, "xyz": [0.32, 0.186, 0.643]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 14, "xyz": [0.677, 0.305, 0.683]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 15, "xyz": [0.788, 0.693, 0.644]}},
|
||||
{"command": "mesh.node.add", "params": {"label": 16, "xyz": [0.165, 0.745, 0.702]}},
|
||||
{"command": "mesh.element.add", "params": {"label": 1, "kind": "hex8", "nodes": [9, 10, 11, 12, 13, 14, 15, 16]}},
|
||||
{"command": "mesh.element.add", "params": {"label": 2, "kind": "hex8", "nodes": [1, 2, 3, 4, 9, 10, 11, 12]}},
|
||||
{"command": "mesh.element.add", "params": {"label": 3, "kind": "hex8", "nodes": [13, 14, 15, 16, 5, 6, 7, 8]}},
|
||||
{"command": "mesh.element.add", "params": {"label": 4, "kind": "hex8", "nodes": [1, 2, 10, 9, 5, 6, 14, 13]}},
|
||||
{"command": "mesh.element.add", "params": {"label": 5, "kind": "hex8", "nodes": [12, 11, 3, 4, 16, 15, 7, 8]}},
|
||||
{"command": "mesh.element.add", "params": {"label": 6, "kind": "hex8", "nodes": [1, 9, 12, 4, 5, 13, 16, 8]}},
|
||||
{"command": "mesh.element.add", "params": {"label": 7, "kind": "hex8", "nodes": [10, 2, 3, 11, 14, 6, 7, 15]}},
|
||||
{"command": "model.set.create", "params": {"name": "all", "elements": [1, 2, 3, 4, 5, 6, 7]}},
|
||||
{"command": "model.material.create", "params": {"name": "Mat", "elastic": {"type": "isotropic", "young": 1000000.0, "poisson": 0.25}}},
|
||||
{"command": "model.section.create", "params": {"name": "cube", "set": "all", "material": "Mat", "kind": {"type": "solid"}, "formulation": {"incompatible_modes": true}}},
|
||||
{"command": "model.set.create", "params": {"name": "corner1", "nodes": [1]}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "u1", "type": "displacement", "target": {"set": "corner1"}, "values": [0.0, 0.0, 0.0, null, null, null]}},
|
||||
{"command": "model.set.create", "params": {"name": "corner2", "nodes": [2]}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "u2", "type": "displacement", "target": {"set": "corner2"}, "values": [0.001, 0.0005, 0.0005, null, null, null]}},
|
||||
{"command": "model.set.create", "params": {"name": "corner3", "nodes": [3]}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "u3", "type": "displacement", "target": {"set": "corner3"}, "values": [0.0015, 0.0015, 0.001, null, null, null]}},
|
||||
{"command": "model.set.create", "params": {"name": "corner4", "nodes": [4]}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "u4", "type": "displacement", "target": {"set": "corner4"}, "values": [0.0005, 0.001, 0.0005, null, null, null]}},
|
||||
{"command": "model.set.create", "params": {"name": "corner5", "nodes": [5]}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "u5", "type": "displacement", "target": {"set": "corner5"}, "values": [0.0005, 0.0005, 0.001, null, null, null]}},
|
||||
{"command": "model.set.create", "params": {"name": "corner6", "nodes": [6]}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "u6", "type": "displacement", "target": {"set": "corner6"}, "values": [0.0015, 0.001, 0.0015, null, null, null]}},
|
||||
{"command": "model.set.create", "params": {"name": "corner7", "nodes": [7]}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "u7", "type": "displacement", "target": {"set": "corner7"}, "values": [0.002, 0.002, 0.002, null, null, null]}},
|
||||
{"command": "model.set.create", "params": {"name": "corner8", "nodes": [8]}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "u8", "type": "displacement", "target": {"set": "corner8"}, "values": [0.001, 0.0015, 0.0015, null, null, null]}},
|
||||
{"command": "model.step.create", "params": {"name": "Patch", "procedure": {"type": "static"}, "boundary_conditions": ["u1", "u2", "u3", "u4", "u5", "u6", "u7", "u8"], "loads": []}},
|
||||
{"command": "solve.static", "params": {}, "id": "solve"}
|
||||
]
|
||||
Reference in new issue
Block a user