b5814a304f6a88725433939ae23f92625a6cd5a1
1
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8615fc5783 |
rtx-fea: verify elastostatics by manufactured solution — second order confirmed
Performance Benchmarks / Run Benchmarks (push) Canceled after 0s
CI / Format Check (push) Canceled after 0s
CI / Clippy Check (push) Canceled after 0s
CI / Build (macos-latest) (push) Canceled after 0s
CI / Build (ubuntu-latest) (push) Canceled after 0s
CI / Test (macos-latest) (push) Canceled after 0s
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Build CPU-Only (Explicit) (push) Canceled after 0s
CI / Python Bindings (maturin) (macos-latest) (push) Canceled after 0s
CI / Python Bindings (maturin) (ubuntu-latest) (push) Canceled after 0s
CI / WASM Build + Size Check (push) Canceled after 0s
CI / Distributed Training Tests (push) Canceled after 0s
CI / CI Success (push) Canceled after 0s
Documentation / Build API Documentation (push) Canceled after 0s
Documentation / Build User Guide (push) Canceled after 0s
Adds the Method of Manufactured Solutions to this crate, and it immediately
paid for itself by finding a bug that every existing test missed.
MMS asserts something stronger than "close enough to a value someone
believed": that the discretisation converges to the exact solution at the
rate the theory predicts. Choose a smooth field, substitute it into the
governing equations, and whatever they fail to balance is the body force
that makes it exact. Solve, refine, read off log2(e_h / e_h/2).
Observed order for Quad4 displacement in L2:
n = 8 L2 error = 7.816681e-3 order -
n = 16 L2 error = 1.962845e-3 order 1.99
n = 32 L2 error = 4.912786e-4 order 2.00
(n = 64 reads 2.00 as well, at ten times the cost)
That verifies the whole chain at once -- element matrices, quadrature,
Jacobian, assembly, DOF numbering, constraints and the linear solver --
against a solution none of them can represent exactly. It is the check
that none of the sixteen defects fixed in this crate would have survived.
The manufactured field is u = sin(pi x) sin(pi y), v = x^2(1-x) y(1-y):
smooth, not in the bilinear element space, with the two components
different in form and a non-zero shear strain, so the shear block of the
constitutive matrix is exercised rather than skipped.
Found by it: `compute_shape_functions` inferred how many parametric
coordinates to pass from the coordinate *values* --
match coords.eta() {
0.0 if coords.zeta() == 0.0 => vec![coords.xi()], // 1 component
...
-- so any evaluation on an axis was handed a one-component slice, which
every 2-D and 3-D element rejects. That includes the element centre and
the middle point of every odd-order Gauss rule. It survived only because
the default 2-point rule never samples zero; asking for a 3-point rule to
integrate the error was enough to trip it. Dimensionality now comes from
the element, which is where it belongs.
Two prerequisites, both real functional gaps rather than test scaffolding:
- Consistent body-force integration. `BodyForceBC` distributed load as
force * volume / num_nodes, which is exact only for a constant force
on a symmetric element and otherwise first-order -- enough to cap the
measured order of the whole solver at 1 regardless of the element.
`ElementMatrixComputer::compute_body_force_vector` now integrates
the consistent form, taking the force as a closure so a spatially
varying load can be expressed at all.
- Non-homogeneous Dirichlet conditions did not exist.
`StaticLinearAnalysis` read the prescribed value out of the boundary
condition and discarded it, and `extract_free_system` built the
reduced right-hand side without the K_fc u_c coupling, so every
Dirichlet condition behaved as zero whatever the caller asked for.
`GlobalSystem::set_prescribed_value` and the coupling term close
that, reusing `extract_submatrix` and `multiply_vector` rather than
a dof-by-dof loop.
560 tests across the three crates, 0 failing.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
|