Every number below is measured, not claimed. The solver the product uses is run against closed-form elasticity — solutions with no adjustable parameters — and the disagreement is published whatever it is.
Report generated 15 August 2026, 13:51 UTC · linear-elastic tet10, the solver the product uses · E = 210000 MPa, ν = 0.3
4 of 4 gating cases pass. 0 case(s) report without gating.
| Case | Closed form | Measured | Error | Band | Status |
|---|---|---|---|---|---|
| cantilever-slender-end-load d = P L^3 / (3 E I) — Euler-Bernoulli, end-loaded cantilever | 0.7619 | 0.74816 | 1.8% | 5% | ✓ gates the build |
| cantilever-stubby-end-load d = P L^3 / (3 E I) — same formula, deliberately outside its range | 0.02381 | 0.023647 | 0.7% | 8% | ✓ gates the build |
| axial-bar-extension d = P L / (A E) — uniaxial extension, exact for a prismatic solid | 0.047619 | 0.047044 | 1.2% | 3% | ✓ gates the build |
| shaft-torsion-circular theta = T L / (G J), rim displacement = theta r — St Venant, exact for a circle | 0.059115 | 0.061338 | 3.8% | 8% | ✓ gates the build |
A disagreement that is real but not yet understood should not block a release, and should not be hidden either. The alternative — widening the tolerance until it passes — is how a validation suite turns into decoration. Those cases are below, in full, including what was ruled out and what remains unexplained.
Was 36.3% soft (0.0806 mm against a closed form of 0.0591 mm). Now 3.8% (0.0613 mm) and passing. The cause was the applied load, not the solver's stiffness.
The torque was applied as a tangential traction over the end face. Its resultant MOMENT was exact by construction — rv x (a x rv) = a|rv|^2 whenever rv.a = 0, so M = torque_nmm.a on any mesh whatsoever. Its resultant FORCE was not: that is c * a x sum(w*rv), which vanishes only when the area-weighted centroid of the loaded nodes lies exactly on the axis. True of a symmetric mesh; false of an unstructured tet mesh on a round face.
The residual force was small and mattered enormously. A slender shaft's bending compliance is orders of magnitude above its torsional compliance, so a small transverse force produces a tip deflection going as L^3 while the twist goes as L. The contamination therefore grows as ~L^2 — length-dependent and mesh-independent, which is precisely the signature that had ruled out every other explanation: +7.3% at L=80, +36.3% at L=150, unchanged across a twelvefold refinement.
Worth recording that the diagnostic originally written down here — integrate the applied nodal forces into a resultant moment and compare against torque_nmm — would have come back CLEAN and taught us nothing, because the moment was never the problem. The force resultant was the check that mattered. Both are now measured from the assembled load vector on every torsion run and reported as applied_resultants, so the solver states what it applied rather than what it was asked for.
THE REMAINING 3.8% IS NOW EXPLAINED (2026-08-15), and the sentence that stood here was the thing blocking it: 'St Venant is exact for a circle, so there is no section-shape approximation to blame.' There is one. The solver is never given a circle.
gmsh remeshes the STL surface at the SOLVER's edge length, not at the facet size of the export. At 3.5 mm on a 20 mm shaft that inscribes roughly an 18-sided polygon in the circle — vertices on the circle, chords cutting inside it. An inscribed polygon has less polar moment than the circle it is drawn in, so the meshed shaft is genuinely more slender than the one that was asked for, and genuinely twists more. The FEA was giving a correct answer to a slightly different question.
Measured, not assumed: J is integrated over the mesh itself on every run (_section_J in run_fea.py) and reported. The sweep, varying the deficit by mesh size, diameter and length:
d=10 mesh=3.5 J deficit 12.92% nominal +15.40% as-meshed +0.49%
d=20 mesh=5.0 J deficit 7.23% nominal +7.99% as-meshed +0.18%
d=20 mesh=3.5 J deficit 5.02% nominal +3.76% as-meshed -1.45%
d=20 L=80 J deficit 3.96% nominal +1.80% as-meshed -2.23%
d=30 mesh=3.5 J deficit 2.56% nominal +0.55% as-meshed -2.02%
The nominal error is a monotone function of the deficit and vanishes with it; correcting for the deficit collapses a 15.4% disagreement to 0.5%. Internal check: the J deficit is twice the volume deficit in every row, which is what J proportional to A^2 requires for a near-circular section — so the integration is not inventing the effect it was written to find.
Two things were ruled out rather than assumed away. End restraint: a circular shaft in St Venant torsion does not warp and has no radial displacement, so a fully clamped end is exactly compatible with the closed form — and it could only stiffen, while the observed error is soft. Traction distribution: the applied load is c*w*(a x rv), whose magnitude grows linearly with radius, which IS the exact St Venant field, so there is no end-effect to invoke. The STL tessellation itself is a red herring — at the default 0.001 mm chordal tolerance that is ~222 facets, a 0.03% effect, three orders below what is observed.
So the case now gates on the AS-MESHED comparison at 3%, which is the number that tests the solver, and reports the nominal error, which is the number that tests the whole product. Do NOT widen either band. If the nominal error needs to come down, the fix is a finer surface mesh on round parts, not a bigger tolerance — and note that refining is not free here: 2.5 mm on this shaft trips gmsh's overlapping-facets check outright and 4.0 mm had not finished meshing after fifteen minutes, which is why the sweep moves diameter as well as mesh size.
The product consequence is recorded in FEA_LIMITATIONS.md: FEA on round features is CONSERVATIVE, over-predicting deflection by roughly the polar-moment deficit, which scales as (mesh/d)^2.