1D elements I: trusses (rod2, rod3), point masses, rotary inertia, springs and dashpots (#38)

* Model, fem and decks: point masses, rotary inertia, springs, dashpots and rod3 trusses

Model: PointMass and Spring definitions (spring | dashpot; to ground or
two-point; along a degree of freedom, a vector or the line of the ends) on a
set or reference point, resolved per node; ElementKind::Rod3. fem: rod2/rod3
truss kernel on Basis::Line2/Line3 declaring ElementDofs (translations).
Decks: Abaqus T3D3, MASS, ROTARYI, SPRING1/2/A, DASHPOT1/2/A; Nastran CONM1,
CELAS2, CDAMP2; LS-DYNA ELEMENT_MASS/INERTIA and ELEMENT_DISCRETE; what a
format cannot take is reported. Commands model.mass.* and model.spring.*.

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

* Implicit solver: trusses, point masses, rotary inertia and springs on the DofLayout

Trusses declare their translations like solids; point masses, inertia and
springs ask the layout for the kinds they need at their nodes (translations,
rotations), and reference points they use get six degrees of freedom. The
matrix pattern takes rows for those points; dashpots are ignored with a
warning. Existing results are bit-identical (hash-checked).

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

* Explicit solver: trusses, point masses, springs and dashpots on the node-major layout

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

* docs: fem.md on trusses and discrete elements in the layout; regenerate features.md

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

* docs: trusses in plane models and corotational explicit trusses

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 21:36:46 -04:00
1 parent 5e5a2ae251
commit 15a9ac9157
53 files changed
+3626 -110

No files matched your search

+19 -7
View File
@@ -138,8 +138,13 @@ module docs; ADR 0001 records why the linear algebra is our own.
quad4, quad8), chosen by the section kind, and the model then has two degrees of freedom per
node: the 2D elements declare `ElementDofs::new(DofSet::PLANE)` (Ux, Uy) to the `DofLayout`. A 2D model
lies in the XY plane (axisymmetric: x the radius, Y the axis; nodes on the axis are held
radially), is loaded on element edges, and cannot mix with solids or couplings yet. Every reference point a coupling
ties to the mesh gets six degrees of freedom (translations, rotations) after the mesh's. Shells
radially), is loaded on element edges, and cannot mix with solids or couplings yet. Rod
sections' rod2 and rod3 elements are trusses (`modelcraft_fem::truss`). Point masses, rotary
inertia and springs (`Resolved::masses`, `springs`, expanded per node by the model) assemble on
the unknowns their nodes are given (`discrete::needs`, `discrete::dof_of`); dashpots are
ignored with a warning (no velocities in static and frequency steps). Every reference point a
coupling or a discrete element uses 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
@@ -181,7 +186,10 @@ and rigid-body modes.
(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).
a kinematically coupled point (twist and shear stress). `crates/solver/tests/one_d.rs`: member
forces of determinate trusses (a plane Pratt truss, a space tripod) against the method of joints,
the three-bar truss, a rod3 constant-stress patch and a bar hanging under its weight, spring–mass,
skew springs, the two-mass chain, a bar with a tip mass and the torsional pendulum.
## Explicit solver
@@ -192,9 +200,11 @@ number their degrees of freedom with `modelcraft_fem::DofLayout` (docs/fem.md).
1. **System.** `Model::resolve()`; hex8 sections with reduced integration become one-point
uniform-strain hexahedra with Flanagan–Belytschko hourglass control, tet4 sections Bonet–Burton
average nodal pressure tetrahedra (`modelcraft_fem::uniform` holds their kinematics). Other
element kinds and formulations, couplings, reference points and moments return "not supported
yet". Masses are row-sum lumped. A zero-valued boundary condition holds a degree of freedom; a
average nodal pressure tetrahedra (`modelcraft_fem::uniform` holds their kinematics), rod2 and
rod3 trusses (`discrete`). Point masses add to the lumped mass; springs and dashpots (on the
previous half increment's velocity) add internal and viscous forces and their own stable
increment. Other element kinds and formulations, couplings, reference points, rotary inertia,
rotational springs and moments return "not supported yet". Masses are row-sum lumped. A zero-valued boundary condition holds a degree of freedom; a
displacement value is reached at constant velocity over the step. Loads act in full from the
start. The step lists initial velocities and fixed frictionless rigid planes by set.
2. **Time step.** Each element's highest frequency is bounded in closed form (exact for a cube);
@@ -227,7 +237,9 @@ only): stress waves in hex8 and tet4 bars (front at c·t, σ = ρ c v, work inpu
rigid wall (contact time 2L/c, rebound speed, plateau force ρ c v₀ A), the energy balance,
bit-for-bit repeatability; Dienes' simple shear for both rates, a stressed element turned rigidly
by 90°, the J2 uniaxial curve and unloading at large strain, damage failure at the fracture
strain, and the Taylor bar against Taylor's 1948 estimate; in the engine (`solve.rs`), a
strain, and the Taylor bar against Taylor's 1948 estimate; `crates/explicit/tests/one_d.rs`:
spring–mass period, damped decay rate and period, a dashpot alone, two masses on a line spring,
waves in rod2 and rod3 bars; in the engine (`solve.rs`), a
cantilever's free-vibration period against `solve.frequency`.
## Lattice Boltzmann solver
+6 -6
View File
@@ -19,10 +19,10 @@ hex8/20/27 with first and second derivatives).
| Element | Use | Status |
|---|---|---|
| Point mass | Lumped mass at a node or reference point (isotropic or per direction) | in progress (1D elements I) |
| Rotary inertia | Inertia tensor at a 6-DOF node | in progress (1D elements I) |
| Spring to ground / two-point spring | Linear spring in a fixed direction or along the line of nodes | in progress (1D elements I) |
| Dashpot to ground / two-point | Linear viscous damper (dynamic steps; ignored in static) | in progress (1D elements I) |
| Point mass | Lumped mass at a node or reference point (isotropic or per direction) | done (implicit, explicit; Abaqus MASS, Nastran CONM1, LS-DYNA ELEMENT_MASS; per direction: Nastran only) |
| Rotary inertia | Inertia tensor at a 6-DOF node | done (implicit; Abaqus ROTARYI, Nastran CONM1, LS-DYNA ELEMENT_INERTIA; explicit when it has rotations) |
| Spring to ground / two-point spring | Linear spring in a fixed direction or along the line of nodes | done (implicit, explicit translational; Abaqus SPRING1/2/A, Nastran CELAS2, LS-DYNA ELEMENT_DISCRETE; skew fixed directions: LS-DYNA only) |
| Dashpot to ground / two-point | Linear viscous damper (dynamic steps; ignored in static) | done (explicit; ignored with a warning in static and frequency steps; Abaqus DASHPOT1/2/A, Nastran CDAMP2, LS-DYNA ELEMENT_DISCRETE) |
| Nonstructural mass | Mass spread over a region without stiffness | planned |
| Connectors | Kinematic joints (hinge, slot, universal…) with elasticity, damping, stops | planned (M7) |
@@ -30,8 +30,8 @@ hex8/20/27 with first and second derivatives).
| Element | Use | Status |
|---|---|---|
| Truss, 2-node (2D and 3D) | Axial members, cables (compression allowed) | in progress (1D elements I) |
| Truss, 3-node (2D and 3D) | Curved axial members | in progress (1D elements I) |
| Truss, 2-node (2D and 3D) | Axial members, cables (compression allowed) | done (rod2: implicit, in plane models with their two unknowns per node; explicit, corotational under nonlinear geometry; Abaqus T3D2 / T2D2, Nastran CROD, LS-DYNA truss beam (3D models)) |
| Truss, 3-node (2D and 3D) | Curved axial members | done (rod3: implicit, plane models too; explicit with small displacements; Abaqus T3D3 / T2D3; no Nastran or LS-DYNA counterpart) |
| Beam, 2-node Timoshenko, 3D | Frames, stiffeners; shear deformable | in progress (shells and beams) |
| Beam, 2-node Euler–Bernoulli (cubic), 2D and 3D | Slender frames; exact for end-loaded prismatic members | planned (1D elements II) |
| Beam, 3-node Timoshenko (quadratic), 2D and 3D | Curved and stocky beams | planned (1D elements II) |
+3 -3
View File
@@ -5,7 +5,7 @@ Generated from the capability catalogue (`crates/engine/src/catalogue.rs`) by
Every entry is a toolbar button. **Ready** entries run their command; **coming soon** entries are
shown greyed with the roadmap milestone that brings them (ROADMAP.md).
48 ready, 53 coming soon.
50 ready, 51 coming soon.
## Geometry
@@ -106,8 +106,8 @@ shown greyed with the roadmap milestone that brings them (ROADMAP.md).
| Contact | Find Contacts — Detect contact pairs automatically | coming soon (M7) | |
| Contact | Rigid Wall — Rigid walls for explicit dynamics | coming soon (M10) | |
| Connectors | Bolt Load — Bolt pretension | coming soon (M7) | |
| Connectors | Spring — Springs and dashpots | coming soon (M7) | |
| Connectors | Point Mass — Point masses and inertia | coming soon (M7) | |
| Connectors | Spring — Spring or dashpot to the ground or between two points, along a direction or their line | ready | `model.spring.create`, `model.spring.edit`, `model.spring.delete` |
| Connectors | Point Mass — Point mass and rotary inertia at nodes or a reference point | ready | `model.mass.create`, `model.mass.edit`, `model.mass.delete` |
| Connectors | Connector — Connector elements between points | coming soon (M7) | |
| Coupled | FSI Interface — The fluid–structure interface | coming soon (M13) | |
+6
View File
@@ -39,6 +39,12 @@ Lookups: `node(label)` / `slot(label)` (a slot is a position: mesh nodes `0..nod
`point_slot(k)`), `dof(slot, kind)`, `range(slot)`, `kinds(slot)`, `locate(dof) -> (slot,
kind)`, `element_dofs(slots, kinds)`, `describe(dof)`, `stride()` (uniform layouts).
Trusses declare `modelcraft_fem::truss::DOFS` (translations, on `Basis::Line2`/`Line3`).
Point masses, springs and dashpots are not mesh elements: the implicit solver asks the layout
for what each needs at its nodes (`modelcraft_solver::discrete::needs`: translations for a mass
or a translational spring, rotations for an inertia or a torsional spring; a reference point
they use is a point with six) and finds its unknowns with `discrete::dof_of`.
Solvers: `modelcraft_solver::system::Mesh::layout` numbers the implicit system (mesh nodes,
then six per coupled reference point); assembly (`sparse::add_block(k, layout, slots, kinds,
data)`, `add_scalar`, `add_diagonal`) works for any mix of kinds per node, so a solid sharing
+2 -1
View File
@@ -56,7 +56,8 @@ products are run, no documentation text is copied). Status: **done**, **started*
| Model | Steps: nonlinear static, explicit dynamics, heat transfer; amplitudes | M7–M8 | | planned |
| Interaction | Tie between non-matching meshes | M7 | | planned |
| Interaction | Contact (general and pairs), friction, automatic pair detection | M7 | | planned |
| Interaction | Bolt pretension, springs, point masses, connectors | M7 | | planned |
| Interaction | Springs and dashpots (ground or two-point; DOF, vector or line), point masses with rotary inertia | M4 | | done (implicit; explicit translational; all three decks with what each cannot take reported) |
| Interaction | Bolt pretension, connectors | M7 | | planned |
| Decks | Abaqus input writer (`deck.write`, flat deck; reports what Abaqus cannot express) | M3 | | done |
| 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) |
+10
View File
@@ -997,6 +997,12 @@ the module docs):
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.
- Trusses and discrete elements: the isoparametric bar along its arc, R. D. Cook, D. S. Malkus,
M. E. Plesha, R. J. Witt, *Concepts and Applications of Finite Element Analysis*, 4th ed.,
Wiley 2002, §3.6 and §6.2, and Hughes 2000, §1.10; springs k [n nᵀ, −n nᵀ; −n nᵀ, n nᵀ],
Cook et al. 2002, §2.2 and §2.10; HRZ lumping as above. Verified against the method of joints
(statically determinate trusses), the three-bar truss, the hanging bar, √(k/m), the two-mass
chain and the torsional pendulum √(k_t/J).
- 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; Saint-Venant's principle (tension through a
@@ -1024,6 +1030,10 @@ again in the module docs):
14(5):437–449, 1998.
- Bulk viscosity and its time-step correction: J. von Neumann, R. D. Richtmyer, J. Appl. Phys.
21(3):232–237, 1950; M. L. Wilkins, J. Comput. Phys. 36(3):281–303, 1980.
- Springs and dashpots: lagged-velocity damping and the damped stable increment
Δt ≤ (2/ω)(√(1 + ξ²) − ξ), Belytschko et al. 2014, §6.2–6.3; Gershgorin's bound on
M^{-1/2} K M^{-1/2} per degree of freedom. Verified against the damped oscillator's decay e^{−ξωt}
and period 2π/ω_d.
- Rigid walls as kinematic velocity constraints: T. J. R. Hughes, R. L. Taylor, J. L. Sackman,
A. Curnier, W. Kanoknukulchai, CMAME 8(3):249–276, 1976.
- Verification: d'Alembert's solution of the 1D wave equation (front at c t, σ = ρ c v), the