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,8 @@
|
||||
# Constant-stress patch test, hex20
|
||||
|
||||
A unit cube of eight hex20 cells whose shared points are moved off the regular grid (every
|
||||
face, edge and centre point; the corners stay), so every element is distorted (one mesh.block per cell). Symmetry on the
|
||||
faces x = 0, y = 0 and z = 0; tractions 1, 2 and 3 on the faces x = 1, y = 1 and z = 1
|
||||
(E = 1000, ν = 0.25). The exact solution is the uniform stress diag(1, 2, 3) with strains
|
||||
ε_i = (σ_i − ν(σ_j + σ_k))/E, which every conforming element of a convergent formulation
|
||||
reproduces exactly on any mesh.
|
||||
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"title": "Constant-stress patch test, hex20",
|
||||
"kind": "theory",
|
||||
"source": "Irons and Razzaque, 'Experience with the patch test for convergence of finite elements', in Aziz (ed.), The Mathematical Foundations of the Finite Element Method, Academic Press 1972, pp. 557–587; MacNeal and Harder, Finite Elements in Analysis and Design 1 (1985) 3–20, constant-stress loading, p. 14 Table 7",
|
||||
"quantities": [
|
||||
{
|
||||
"id": "ux",
|
||||
"quantity": "u_x at the corner (1, 1, 1)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Load",
|
||||
"at": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/displacement/0"
|
||||
},
|
||||
"value": -0.00025,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "uy",
|
||||
"quantity": "u_y at the corner (1, 1, 1)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Load",
|
||||
"at": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/displacement/1"
|
||||
},
|
||||
"value": 0.001,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "uz",
|
||||
"quantity": "u_z at the corner (1, 1, 1)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Load",
|
||||
"at": [
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/displacement/2"
|
||||
},
|
||||
"value": 0.00225,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "sxx",
|
||||
"quantity": "σ_xx at the inner node (0.46, 0.55, 0.53)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Load",
|
||||
"at": [
|
||||
[
|
||||
0.46,
|
||||
0.55,
|
||||
0.53
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/0"
|
||||
},
|
||||
"value": 1.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "syy",
|
||||
"quantity": "σ_yy at the inner node (0.46, 0.55, 0.53)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Load",
|
||||
"at": [
|
||||
[
|
||||
0.46,
|
||||
0.55,
|
||||
0.53
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/1"
|
||||
},
|
||||
"value": 2.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "szz",
|
||||
"quantity": "σ_zz at the inner node (0.46, 0.55, 0.53)",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Load",
|
||||
"at": [
|
||||
[
|
||||
0.46,
|
||||
0.55,
|
||||
0.53
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/2"
|
||||
},
|
||||
"value": 3.0,
|
||||
"tolerance": {
|
||||
"relative": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding"
|
||||
},
|
||||
{
|
||||
"id": "sxy",
|
||||
"quantity": "σ_xy at the inner node",
|
||||
"measure": {
|
||||
"command": "solve.probe",
|
||||
"params": {
|
||||
"step": "Load",
|
||||
"at": [
|
||||
[
|
||||
0.46,
|
||||
0.55,
|
||||
0.53
|
||||
]
|
||||
]
|
||||
},
|
||||
"pointer": "/nodes/0/stress/3"
|
||||
},
|
||||
"value": 0.0,
|
||||
"tolerance": {
|
||||
"absolute": 1e-09
|
||||
},
|
||||
"reason": "a patch test is passed exactly: the tolerance only admits rounding (stresses of order 1)"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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": 1.0000000000000034e-9,
|
||||
"value": 1.0000000000000033
|
||||
},
|
||||
"sxy": {
|
||||
"band": 1.0000000000005828e-12,
|
||||
"value": 5.826462044860843e-16
|
||||
},
|
||||
"syy": {
|
||||
"band": 2.0000000000000026e-9,
|
||||
"value": 2.0000000000000027
|
||||
},
|
||||
"szz": {
|
||||
"band": 3.0000000000000025e-9,
|
||||
"value": 3.000000000000002
|
||||
},
|
||||
"ux": {
|
||||
"band": 2.500000000000003e-13,
|
||||
"value": -0.0002500000000000003
|
||||
},
|
||||
"uy": {
|
||||
"band": 1.000000000000001e-12,
|
||||
"value": 0.0010000000000000009
|
||||
},
|
||||
"uz": {
|
||||
"band": 2.2500000000000027e-12,
|
||||
"value": 0.0022500000000000024
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
[
|
||||
{"command": "mesh.block", "params": {"body": "Cube", "kind": "hex20", "corners": [[0.0, 0.0, 0.0], [0.46, 0.0, 0.0], [0.55, 0.47, 0.0], [0.0, 0.46, 0.0], [0.0, 0.0, 0.53], [0.56, 0.0, 0.45], [0.46, 0.55, 0.53], [0.0, 0.47, 0.54]], "divisions": [1, 1, 1], "faces": {"6": "x0", "3": "y0", "1": "z0"}}},
|
||||
{"command": "mesh.block", "params": {"body": "Cube", "kind": "hex20", "corners": [[0.46, 0.0, 0.0], [1.0, 0.0, 0.0], [1.0, 0.55, 0.0], [0.55, 0.47, 0.0], [0.56, 0.0, 0.45], [1.0, 0.0, 0.54], [1.0, 0.46, 0.45], [0.46, 0.55, 0.53]], "divisions": [1, 1, 1], "faces": {"4": "x1", "3": "y0", "1": "z0"}}},
|
||||
{"command": "mesh.block", "params": {"body": "Cube", "kind": "hex20", "corners": [[0.0, 0.46, 0.0], [0.55, 0.47, 0.0], [0.56, 1.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.47, 0.54], [0.46, 0.55, 0.53], [0.55, 1.0, 0.54], [0.0, 1.0, 0.45]], "divisions": [1, 1, 1], "faces": {"6": "x0", "5": "y1", "1": "z0"}}},
|
||||
{"command": "mesh.block", "params": {"body": "Cube", "kind": "hex20", "corners": [[0.55, 0.47, 0.0], [1.0, 0.55, 0.0], [1.0, 1.0, 0.0], [0.56, 1.0, 0.0], [0.46, 0.55, 0.53], [1.0, 0.46, 0.45], [1.0, 1.0, 0.53], [0.55, 1.0, 0.54]], "divisions": [1, 1, 1], "faces": {"4": "x1", "5": "y1", "1": "z0"}}},
|
||||
{"command": "mesh.block", "params": {"body": "Cube", "kind": "hex20", "corners": [[0.0, 0.0, 0.53], [0.56, 0.0, 0.45], [0.46, 0.55, 0.53], [0.0, 0.47, 0.54], [0.0, 0.0, 1.0], [0.55, 0.0, 1.0], [0.56, 0.46, 1.0], [0.0, 0.55, 1.0]], "divisions": [1, 1, 1], "faces": {"6": "x0", "3": "y0", "2": "z1"}}},
|
||||
{"command": "mesh.block", "params": {"body": "Cube", "kind": "hex20", "corners": [[0.56, 0.0, 0.45], [1.0, 0.0, 0.54], [1.0, 0.46, 0.45], [0.46, 0.55, 0.53], [0.55, 0.0, 1.0], [1.0, 0.0, 1.0], [1.0, 0.47, 1.0], [0.56, 0.46, 1.0]], "divisions": [1, 1, 1], "faces": {"4": "x1", "3": "y0", "2": "z1"}}},
|
||||
{"command": "mesh.block", "params": {"body": "Cube", "kind": "hex20", "corners": [[0.0, 0.47, 0.54], [0.46, 0.55, 0.53], [0.55, 1.0, 0.54], [0.0, 1.0, 0.45], [0.0, 0.55, 1.0], [0.56, 0.46, 1.0], [0.46, 1.0, 1.0], [0.0, 1.0, 1.0]], "divisions": [1, 1, 1], "faces": {"6": "x0", "5": "y1", "2": "z1"}}},
|
||||
{"command": "mesh.block", "params": {"body": "Cube", "kind": "hex20", "corners": [[0.46, 0.55, 0.53], [1.0, 0.46, 0.45], [1.0, 1.0, 0.53], [0.55, 1.0, 0.54], [0.56, 0.46, 1.0], [1.0, 0.47, 1.0], [1.0, 1.0, 1.0], [0.46, 1.0, 1.0]], "divisions": [1, 1, 1], "faces": {"4": "x1", "5": "y1", "2": "z1"}}},
|
||||
{"command": "model.set.create", "params": {"name": "all", "geometry": [{"body": "Cube"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "x0", "geometry": [{"body": "Cube", "face": "x0"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "x1", "geometry": [{"body": "Cube", "face": "x1"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "y0", "geometry": [{"body": "Cube", "face": "y0"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "y1", "geometry": [{"body": "Cube", "face": "y1"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "z0", "geometry": [{"body": "Cube", "face": "z0"}]}},
|
||||
{"command": "model.set.create", "params": {"name": "z1", "geometry": [{"body": "Cube", "face": "z1"}]}},
|
||||
{"command": "model.material.create", "params": {"name": "Mat", "elastic": {"type": "isotropic", "young": 1000.0, "poisson": 0.25}}},
|
||||
{"command": "model.section.create", "params": {"name": "solid", "set": "all", "material": "Mat", "kind": {"type": "solid"}}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "sym_x", "type": "symmetry", "target": {"set": "x0"}, "plane": "x"}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "sym_y", "type": "symmetry", "target": {"set": "y0"}, "plane": "y"}},
|
||||
{"command": "model.boundary_condition.create", "params": {"name": "sym_z", "type": "symmetry", "target": {"set": "z0"}, "plane": "z"}},
|
||||
{"command": "model.load.create", "params": {"name": "tx", "type": "traction", "set": "x1", "vector": [1.0, 0, 0]}},
|
||||
{"command": "model.load.create", "params": {"name": "ty", "type": "traction", "set": "y1", "vector": [0, 2.0, 0]}},
|
||||
{"command": "model.load.create", "params": {"name": "tz", "type": "traction", "set": "z1", "vector": [0, 0, 3.0]}},
|
||||
{"command": "model.step.create", "params": {"name": "Load", "procedure": {"type": "static"}, "boundary_conditions": ["sym_x", "sym_y", "sym_z"], "loads": ["tx", "ty", "tz"]}},
|
||||
{"command": "solve.static", "params": {}, "id": "solve"}
|
||||
]
|
||||
Reference in new issue
Block a user