Implicit solver: reference points, couplings, moments, wedge6 (M4) (#26)

* fem: wedge6 element (triangle × interval, 3 × 2 points), patch and cantilever tests

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* solver: reference points, kinematic and distributing couplings, moments by constraint elimination

Coupled reference points get six degrees of freedom; kinematic couplings are rigid
links, distributing couplings least-squares interpolation constraints. Every
constraint row and prescribed value is eliminated master-slave (Abel-Shephard
pivot choice), so the reduced matrix stays SPD; no coupling gives the old
elimination bit for bit. Verified: rigid motion of a coupled block, clamping
through a point, distributing tension vs pressure, bending and tube torsion.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* engine: reference point results in solve.static and solve.probe

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* docs: couplings, moments and wedge6 in the solver docs, literature and roadmap

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* solver: simplify constraint elimination and reference point plumbing

Rows combine by one sort; T_f transposed once; K and M reduced in one pass on a
shared pattern; prescribed motion computed once; reference point loads and BCs go
through Resolved like node ones (Mesh::label_dofs); one dof-direction rule;
StepResult::locate for probes; dead Csr::restrict removed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

* solver: refuse oversized reductions before allocating them

A held distributing coupling point makes a dense (3N)^2 block; estimate it from
the constraint rows and refuse it against the factorization's memory budget
with a clear message, before anything is built. Other reductions with
dependents count their entries first (stopping at the budget) and reserve
fallibly.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm

---------

Co-authored-by: jyviko <[email protected]>
Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
authored and GitHub committed 2026-10-13 18:21:52 -04:00
1 parent a292212b67
commit 48039639cb
18 files changed
+1502 -199

No files matched your search

+25 -10
View File
@@ -21,7 +21,7 @@ crates in strictly lower layers.
| L0 | `modelcraft-model` | Solver-neutral FE model: nodes and elements by label, their geometry tags, sets, materials, sections, couplings, BCs, loads and steps, the model check and the resolved view the writers read. Knows no file format and no geometry type. | started |
| L1 | `modelcraft-geometry` | The only door to SolidCraft: opens `.solidcraft` designs (rebuilt from their timeline, bodies with persistent face names), B-rep bodies, measures, tessellation into a face-tagged `SurfaceMesh`; face-tagged 3MF files read into the same type without the kernel (docs/formats/tagged-mesh.md). No SolidCraft type in its API. | started |
| L1 | `modelcraft-mesh` | Surface preparation (weld, watertightness, feature edges), robust predicates, Delaunay tetrahedralization and refinement, Voronoi-based optimization, hex meshing, quality metrics. | started |
| L1 | `modelcraft-fem` | Element kernels shared by every structural solver: the element table (tet4, tet10, hex8 full and incompatible modes, hex20 full and reduced), shape functions, quadrature, element stiffness, consistent and lumped mass, body and pressure loads, stresses and their extrapolation, isotropic and orthotropic elasticity. Pure functions, no solver loop. | started |
| L1 | `modelcraft-fem` | Element kernels shared by every structural solver: the element table (tet4, tet10, wedge6, hex8 full and incompatible modes, hex20 full and reduced), shape functions, quadrature, element stiffness, consistent and lumped mass, body and pressure loads, stresses and their extrapolation, isotropic and orthotropic elasticity. Pure functions, no solver loop. | started |
| L1 | `modelcraft-decks` | Abaqus input, Nastran bulk data and LS-DYNA keyword readers and writers, to and from `model`. Text out, no file system; `deck.write` saves it. | started |
| L1 | `modelcraft-render` | Display data without a GPU dependency: the visible faces, element edges and nodes of a model, the orbit camera, a CPU rasterizer for headless snapshots; contour maps later. | started |
| L2 | `modelcraft-solver` | Implicit solver: assembly from the resolved model, boundary conditions, sparse direct solution, linear static and modal analysis, stresses and reactions. The explicit (`modelcraft-explicit`) and lattice Boltzmann (`modelcraft-lbm`) solvers join this layer. | started |
@@ -130,19 +130,29 @@ module docs; ADR 0001 records why the linear algebra is our own.
1. **System.** `Model::resolve()`; each solid section's elements take their material's
elasticity matrix and the section's formulation (`modelcraft_fem::element::ELEMENT_TYPES`, one
row per element kind). Couplings, reference points, moments, shells and beams return "not
supported yet". The step's boundary conditions prescribe translations (rotations do not exist
on solid nodes); its loads become a load vector: forces and tractions from
`Resolved::nodal_loads`, pressure as consistent face loads, gravity and body forces through the
row per element kind: tet4, tet10, wedge6, hex8, hex20). Every reference point a coupling
ties to the mesh gets six degrees of freedom (translations, rotations) after the mesh's. Shells
and beams return "not supported yet". The step's boundary conditions prescribe translations
(rotations do not exist on solid nodes) and a coupled point's six directions; its loads become
a load vector: forces and tractions from `Resolved::nodal_loads`, forces and moments on coupled
reference points, pressure as consistent face loads, gravity and body forces through the
element shape functions.
2. **Assembly** on the node graph (3 × 3 blocks, elements in label order, so sums are
reproducible bit for bit).
3. **Ordering and elimination.** Nested dissection of the nodes by coordinate bisection; free
degrees of freedom numbered in that order; prescribed values moved to the right-hand side (no
penalty).
3. **Ordering and elimination** (`constraints`). Nested dissection of the nodes by coordinate
bisection. Couplings become linear constraint rows: kinematic = rigid link of each coupled
translation to the point's translation and rotation; distributing = the point follows the
least-squares rigid fit of the set's translations (equal weights, the deck writers' choice).
Prescribed values and rows are eliminated master–slave in a fixed order, one dependent degree
of freedom per row (the coupled node or the distributing point while it is free, else the
largest coefficient), giving u = T_f q + T_p u_p; the reduced matrix T_fᵀ K T_f stays
symmetric positive definite (no penalty, no multipliers). Free mesh equations follow the
node order, reference point equations come last. Without couplings T is a selection and the
numbers are those of plain elimination, bit for bit.
4. **Static solution.** Up-looking sparse Cholesky (the factor size is computed and capped before
any value), reactions K u − f, integration-point stresses extrapolated to the nodes and
averaged, von Mises. A zero pivot names the node and direction that can move freely.
any value), reactions T_pᵀ (K u − f) (at nodes and at prescribed reference points, forces and
moments), integration-point stresses extrapolated to the nodes and averaged, von Mises. A zero
pivot names the node or reference point and direction that can move freely.
5. **Frequency.** Shift-invert block Lanczos (block 6, full reorthogonalization) on
K − σM, σ = 0 for a supported structure and slightly negative for a free one, so rigid-body
modes come out at zero; mass-normalized shapes, participation factors and effective masses.
@@ -154,6 +164,11 @@ Verification (`crates/solver/tests/verification.rs`, analytic only): displacemen
patch tests for every element and formulation (exact to round-off), cantilever tip deflection
against Timoshenko with convergence rates of the linear elements, Lamé's cylinder, Kirsch's
plate with a hole (Kt → 3), cantilever and free–free beam frequencies with six rigid-body modes.
`crates/solver/tests/couplings.rs`: a block given a rigid motion through a coupled point
(kinematic and distributing), clamping through a coupled point equals clamping (static and
modes), tension through a distributing coupling against the equivalent pressure away from the
end, pure bending by a moment through a distributing coupling, torsion of a tube by a moment on
a kinematically coupled point (twist and shear stress).
## Commands
+1 -1
View File
@@ -60,7 +60,7 @@ products are run, no documentation text is copied). Status: **done**, **started*
| Decks | Nastran bulk data writer (`deck.write`, SOL 101 or 103 per deck; reports what Nastran cannot express) | M3 | | done |
| Decks | LS-DYNA keyword writer (implicit; explicit in M8) | M3 | | done (implicit static and eigenvalue; beam sections planned) |
| Decks | Readers keeping unknown keywords | M9 | | planned |
| Solve | Own linear static and modal solver, verified against analytic solutions | M4 | yes | started (solid elements: tet4, tet10, hex8, hex20) |
| Solve | Own linear static and modal solver, verified against analytic solutions | M4 | yes | started (solid elements: tet4, tet10, wedge6, hex8, hex20; reference points, kinematic and distributing couplings, moments) |
| Results | Deformed shape, contours, mode shapes, probes, reaction sums | M4 | | started (results in the session, `solve.probe`, reaction sums; display planned) |
| Results | XY and path plots, cuts, display groups, free-body forces, animation | M9 | | planned |
| Results | Readers for public result formats (Nastran OP2, LS-DYNA d3plot, Abaqus `.fil`) | M9 | | planned |
+12 -1
View File
@@ -977,6 +977,17 @@ the module docs):
Lewis, H. D. Simon, SIAM J. Matrix Anal. Appl. 15(1):228–272, 1994; B. N. Parlett, *The
Symmetric Eigenvalue Problem*, SIAM 1998; G. H. Golub, C. F. Van Loan, *Matrix Computations*,
4th ed., 2013.
- Wedge6: the linear triangle times the linear interval; the symmetric three-point triangle rule
(Zienkiewicz, Taylor & Zhu 2013, table 6.3) times two-point Gauss–Legendre.
- Couplings and constraint elimination: rigid links and master–slave elimination by
transformation, R. D. Cook, D. S. Malkus, M. E. Plesha, R. J. Witt, *Concepts and Applications
of Finite Element Analysis*, 4th ed., Wiley 2002, §9.2, and C. A. Felippa, *Introduction to
Finite Element Methods*, ch. 8 (University of Colorado lecture notes); automatic choice of the
dependent degree of freedom, J. F. Abel, M. S. Shephard, IJNME 14(3):464–467, 1979; the
distributing (interpolation) constraint as a least-squares rigid fit with loads spread by
virtual work, G. H. K. Heirman, W. Desmet, Multibody Syst. Dyn. 24(2):219–234, 2010; the
reduced matrix product T_fᵀ K T_f row by row, F. G. Gustavson, ACM TOMS 4(3):250–269, 1978.
- Verification: R. H. MacNeal, R. L. Harder, *A proposed standard set of problems to test finite
element accuracy*, Finite Elem. Anal. Des. 1(1):3–20, 1985 (patch tests); Lamé, Kirsch,
Timoshenko and Euler–Bernoulli closed forms.
Timoshenko and Euler–Bernoulli closed forms; Saint-Venant's principle (tension through a
coupling), pure bending σ = M z / I, torsion of a circular tube φ = T L / (G J), τ = T r / J.