explicit: deformable contact and friction, verified by bars, sliding blocks, the patch test and Hertz

Segment-to-segment penalty contact between element faces: each secondary
face and each main face facing it are projected onto the secondary face's
plane, split into triangles, clipped (Sutherland–Hodgman) and integrated
with a three-point rule per sub-triangle (Puso–Laursen segmentation, the
penalty at the integration points as Fischer–Wriggers), so a uniform
pressure gives the consistent nodal forces on both meshes and the contact
patch test passes on non-matching meshes. Every contact runs both ways at
half the penalty: pairs with each surface as the secondary, general and
self contact face against face. A bucket grid of face boxes every
increment, faces integrated in parallel and their forces added in face
order: the same numbers on any thread count.

The penalty per area ε = s γ min(m/A)/Δt² comes from the lumped masses,
each node's directional area and the stable increment, bounded by
Gershgorin's row sums so contact never shortens the increment. Coulomb
friction with exponential decay by a regularised return map at the
secondary nodes; rigid walls take Coulomb impulses. Contact work and
friction dissipation join the energy balance; each contact reports its
peak force, first and last contact, deepest penetration, friction and the
nodes adjusted at the start (initial penetrations adjusted strain-free or
refused with the node, face and depth); a cap on contact faces.

Verified (crates/explicit/tests/contact.rs, tests/oracle/explicit-*):
colliding bars (2L/c +1.2%, ρcAv₀/2, KE kept to 0.005%, contact energy
back to 8e-5 of it), blocks sliding to a stop on a rigid wall and on a
plate under constant and decaying friction (0.005–0.2%), the patch test
(σ_zz uniform to 0.06%), two spheres colliding against Hertz (peak +2.3%,
duration −0.4%; the oracle case waits for a graded sphere mesher), a free
body untouched by general contact, determinism across threads. Oracle
measures gain `over` (ratios). Existing fixtures do not move.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-14 12:49:45 -04:00
1 parent ecf947c090
commit a30d0b5c5b
37 files changed
+2459 -55

No files matched your search

+14 -2
View File
@@ -255,7 +255,7 @@ number their degrees of freedom with `fieldcraft_fem::DofLayout` (docs/fem.md).
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.
start. The step lists initial velocities and fixed rigid planes (with friction) by set.
2. **Time step.** Each element's highest frequency is bounded in closed form (exact for a cube);
the increment is the step's scale (0.9 by default) times the smallest element increment with
Wilkins' bulk-viscosity correction, recomputed every increment. The ten controlling elements
@@ -280,6 +280,15 @@ number their degrees of freedom with `fieldcraft_fem::DofLayout` (docs/fem.md).
`fem::plasticity`. Elements whose damage reaches 1 or whose plastic strain reaches the
material's erosion strain are eroded (reported with their energy; their nodes keep mass and
momentum). The energy account adds the plastic work and the eroded energy.
7. **Contact (X3).** The model's contacts (`interaction.contact.*`) become interfaces before the
elements are built (nodes that start inside a surface are moved onto it or refused):
segment-to-segment penalty contact both ways (projection, polygon clipping and quadrature over
each pair of facing faces), a bucket-grid search every increment in parallel by faces, a
penalty per area from the masses and the stable increment that never shortens it, and Coulomb
friction by a return map at the secondary nodes; rigid walls take Coulomb impulses. The contact
forces join the equations of motion beside the external ones, their work and the friction
dissipation join the energy account, and each contact's peak force, first and last contact,
deepest penetration and friction are reported (docs/fem.md).
Verification (`crates/explicit/tests/verification.rs` and `large_deformation.rs`, analytic
only): stress waves in hex8 and tet4 bars (front at c·t, σ = ρ c v, work input), a bar striking a
@@ -288,7 +297,10 @@ bit-for-bit repeatability; Dienes' simple shear for both rates, a stressed eleme
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; `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
waves in rod2 and rod3 bars; `crates/explicit/tests/contact.rs`: colliding bars, sliding
blocks under constant and decaying friction on a rigid wall and on a plate, the contact patch
test, Hertz's sphere impact, a free body untouched by general contact, initial penetrations and
thread-count independence; in the engine (`solve.rs`), a
cantilever's free-vibration period against `solve.frequency`.
## Lattice Boltzmann solver
+56
View File
@@ -347,3 +347,59 @@ form (exact), and a tube inflated by a follower pressure while stretched axially
block at a thermal stretch of 1.2 (exact, full and hybrid), a bar held at its ends heated past
yield (exact), the linear limit against the linear and coupled solvers, and tangents with a
temperature field.
crushing stops at the minimum increment, naming it; the caps; what is refused).
## Contact and friction (explicit dynamics)
**Model** (`fieldcraft_model::contact`): a contact names its surfaces as sets of element faces —
a **pair** (`main`, `secondary`) or **general** contact on one surface (self contact) or on every
exterior face of the solids — with Coulomb **friction** μ = μ_k + (μ_s − μ_k) e^{−d γ̇} (static,
kinetic, decay per slip rate), a **penalty scale** s ≤ 1 and what happens to nodes that start
inside the other surface (**adjust**: moved onto it strain-free and reported; **refuse**: the
analysis stops naming the node, the face and the depth). Planar rigid walls take the same friction.
Commands `interaction.contact.pair|general|edit|delete|find`; Abaqus writes `*SURFACE
INTERACTION` with `*FRICTION` (exponential decay), `*CONTACT PAIR` and general `*CONTACT`, LS-DYNA
`*CONTACT_AUTOMATIC_SURFACE_TO_SURFACE` and `_SINGLE_SURFACE` (`fs`, `fd`, `dc`, `sfsa`,
`sfsb`); Nastran and the implicit solver refuse contact by name (implicit contact is M7).
**Geometry** (`fieldcraft_fem::contact`, shared with the implicit solver to come): the closest
point of a triangle (exact region tests) or of a bilinear quadrilateral (projected Newton with the
exact Hessian) to a point, with the signed gap along the face's normal and the lateral offset;
a bucket grid of face boxes whose cell is twice the mean box, grown until the grid and its entries
fit their caps, queried by point or by box with the candidates in face order.
**Kinematics** (`fieldcraft_explicit::contact`): segment to segment. Each secondary face and
each main face facing it (normals within 84° of opposite) are projected onto the secondary face's
plane, split into triangles and clipped against each other; on each overlap triangle a
three-point rule takes the gap g = (x_s − x_m)·n_m between the faces' closest points. Where
g < 0 (no deeper than half the main face's element), a penalty pressure p = ε(−g) acts on the
secondary face's nodes with weights N_i^s along n_m and on the main face's nodes with −N_j^m. For
a uniform pressure across flat faces both meshes receive exactly the consistent nodal forces,
so the contact patch test passes on non-matching meshes. Every contact runs both ways (a pair
with each surface as the secondary, single-surface contact with every face against every other
face that shares no node with it) at half the penalty each.
**Penalty**: ε = s γ min_i(m_i/A_i)/Δt² over the contact's nodes (m_i lumped mass, A_i the node's
area facing one way, Δt the stable increment, γ = 0.3). By Gershgorin's and Weyl's inequalities
the contact adds at most 2 s γ/Δt² to the square of any frequency, which the default increment
scale 0.9 leaves room for: contact never shortens the increment.
**Friction**: at the secondary nodes, by a regularised return map against the main face that
pressed each node most: the elastic predictor t* = P t_n − k_t Δu_T (k_t = ε A_i/2), stick when
|t*| ≤ μ f_n, otherwise slip back to the cone, dissipating μ f_n (|t*| − μ f_n)/k_t. On rigid
walls, a node's tangential velocity changes by at most μ times its normal velocity change.
**Energy**: the contact forces' work (penalty energy plus friction dissipated) is integrated with
the trapezoidal rule and enters the balance; friction dissipation (contact and walls) is
reported apart. **Search** every increment, in parallel by faces, forces added in face order: the
results are the same on any number of threads.
**Verification** (`crates/explicit/tests/contact.rs`, `tests/oracle/explicit-*`): two bars
colliding (contact for 2L/c, interface force ρcAv₀/2, velocities exchanged, kinetic energy kept to
0.01%, the contact energy back to 10⁻⁴ of it), a block sliding to a stop under constant and
decaying friction on a rigid wall and on a deformable plate (distance and time to 0.1–0.5%), the
contact patch test on non-matching meshes (σ_zz uniform to 0.1%), two spheres colliding against
Hertz (peak force +2.3%, duration −0.4% on a graded quarter-sphere mesh), a free body untouched
by general contact on all its faces, initial penetrations adjusted or refused, the face cap, and
bit-for-bit results on one and four threads.
+23 -1
View File
@@ -2,7 +2,7 @@
Generated by `cargo xtask oracle` from [`tests/oracle/`](../tests/oracle/); the policy is [verification.md](verification.md). Every case is our own model, built with FieldCraft commands from the problem's published description, and compared with the reference value its `expected.json` cites, within the stated tolerance and for the stated reason. Accepted results are frozen in each case's `fixture.json`: a later change that moves one beyond its band (10⁻⁹ of its size) fails CI even while the reference still passes. No reference value was produced with a commercial product.
**176 of 182 quantities pass** (6 known failure(s)) in 53 active cases: 44 theory, 9 published benchmark, 0 experiment; 9 pending cases wait for capabilities still being built.
**193 of 199 quantities pass** (6 known failure(s)) in 57 active cases: 48 theory, 9 published benchmark, 0 experiment; 10 pending cases wait for capabilities still being built.
## Theory: closed-form solutions, patch tests and mesh invariants
@@ -28,6 +28,23 @@ Generated by `cargo xtask oracle` from [`tests/oracle/`](../tests/oracle/); the
| [cdt-stepped-block](../tests/oracle/cdt-stepped-block/) | volume of the tetrahedra | 47000 | 47000 | < 1e-7% | 1e-12 rel. | pass | matches |
| [cdt-stepped-block](../tests/oracle/cdt-stepped-block/) | elements that fail the certified Jacobian check | 0 | 0 | ≈ 0 | exact | pass | matches |
| [cdt-stepped-block](../tests/oracle/cdt-stepped-block/) | elements the Jacobian check could not decide | 0 | 0 | ≈ 0 | exact | pass | matches |
| [explicit-bars-collision](../tests/oracle/explicit-bars-collision/) | time of the last contact (the bars touch from t = 0) against 2L/c = 0.2 | 0.2 | 0.20242 | 1.21% | 2% | pass | matches |
| [explicit-bars-collision](../tests/oracle/explicit-bars-collision/) | the largest force across the interface against ρcAv₀/2 = 0.05 | 0.05 | 0.05147 | 2.94% | 4% | pass | matches |
| [explicit-bars-collision](../tests/oracle/explicit-bars-collision/) | velocity of the struck bar's far end after the impact (0: the striker stops) | 0 | -0.0033987 | -3.4e-3 | ± 0.005 | pass | matches |
| [explicit-bars-collision](../tests/oracle/explicit-bars-collision/) | velocity of the struck bar's far end after the impact (v₀ = 0.1) | 0.1 | 0.1034 | 3.4% | 5% | pass | matches |
| [explicit-bars-collision](../tests/oracle/explicit-bars-collision/) | kinetic energy after the impact over ½mv₀² (frictionless elastic impact) | 1 | 0.99995 | -0.00468% | 1% | pass | matches |
| [explicit-bars-collision](../tests/oracle/explicit-bars-collision/) | energy left in the contact after the separation, over ½mv₀² (its drift) | 0 | -7.7435e-5 | -7.7e-5 | ± 0.001 | pass | matches |
| [explicit-contact-patch](../tests/oracle/explicit-contact-patch/) | σ_zz of the lower block's corner element under the interface (element 10) over that of the upper block's corner element over it (element 19) | 1 | 1.0001 | 0.0118% | 0.5% | pass | matches |
| [explicit-contact-patch](../tests/oracle/explicit-contact-patch/) | σ_zz of the lower block's centre element under the interface (element 14) over that of element 19 | 1 | 1.0003 | 0.0287% | 0.5% | pass | matches |
| [explicit-contact-patch](../tests/oracle/explicit-contact-patch/) | σ_zz of the lower block's bottom corner element (element 1) over that of element 19 | 1 | 1.0001 | 0.0134% | 0.5% | pass | matches |
| [explicit-contact-patch](../tests/oracle/explicit-contact-patch/) | σ_zz of the upper block's top far corner element (element 26) over that of element 19 | 1 | 0.99944 | -0.0564% | 0.5% | pass | matches |
| [explicit-contact-patch](../tests/oracle/explicit-contact-patch/) | the force across the interface over −σ_zz A (A = 1) | 1 | 1.0026 | 0.259% | 1% | pass | matches |
| [explicit-contact-patch](../tests/oracle/explicit-contact-patch/) | σ_xx of element 14 over its σ_zz (uniaxial stress: 0) | 0 | -3.6052e-4 | -3.6e-4 | ± 0.005 | pass | matches |
| [explicit-sliding-block-contact](../tests/oracle/explicit-sliding-block-contact/) | distance travelled (top centre node) against ∫ v dv / (g μ(v)) = 2.01524 | 2.0152 | 2.0118 | -0.172% | 1% | pass | matches |
| [explicit-sliding-block-contact](../tests/oracle/explicit-sliding-block-contact/) | velocity of the top centre node after the stop | 0 | ≈ 0 | ≈ 0 | ± 0.03 | pass | matches |
| [explicit-sliding-block-wall](../tests/oracle/explicit-sliding-block-wall/) | distance travelled (top centre node) against v₀²/(2μg) = 1.5 | 1.5 | 1.4999 | -0.0053% | 1% | pass | matches |
| [explicit-sliding-block-wall](../tests/oracle/explicit-sliding-block-wall/) | velocity of the top centre node after the stop | 0 | ≈ 0 | ≈ 0 | ± 0.03 | pass | matches |
| [explicit-sliding-block-wall](../tests/oracle/explicit-sliding-block-wall/) | friction dissipation over ½mv₀² = 2.25 | 1 | 1.0012 | 0.121% | 1% | pass | matches |
| [filleted-bracket-fillet-stress](../tests/oracle/filleted-bracket-fillet-stress/) | largest nodal von Mises stress on the fillet face (MPa) | 213 | mesh-dependent | within 3% | 3% | pass | — |
| [filleted-bracket-fillet-stress](../tests/oracle/filleted-bracket-fillet-stress/) | total reaction x (N) | -2000 | -2000 | < 1e-7% | 1e-9 rel. | pass | matches |
| [filleted-bracket-fillet-stress-coarse](../tests/oracle/filleted-bracket-fillet-stress-coarse/) | largest nodal von Mises stress on the fillet face (MPa) | 213 | mesh-dependent | within 3% | 3% | pass | — |
@@ -206,6 +223,10 @@ Generated by `cargo xtask oracle` from [`tests/oracle/`](../tests/oracle/); the
- **[cantilever-tet10](../tests/oracle/cantilever-tet10/)** (theory): Cantilever under a tip load, Timoshenko deflection (tet10). Source: Timoshenko and Gere, Mechanics of Materials (beam with shear deformation: δ = PL³/3EI + PL/κGA, κ = 5/6 for a rectangle); Cowper, J. Appl. Mech. 33 (1966) 335–340 for the shear coefficient. Tolerances — tip_uz: beam theory vs 3D elasticity (a few tenths of a percent at L/h = 10); quadratic tetrahedra are converged on this mesh; reaction: equilibrium holds to rounding
- **[cdt-cylinder](../tests/oracle/cdt-cylinder/)** (theory): Constrained Delaunay mesh of a cylinder: volume within the chordal bound, valid elements. Source: mesh invariants: an inscribed polygon of sagitta s loses at most 2s/R of a circle's area (elementary geometry); constrained Delaunay tetrahedralization after Diazzi et al., ACM TOG 42(6) 2023. Tolerances — volume: the tessellation inscribes the cylinder within the chordal tolerance s = 0.05: the polygon section loses between 0 and 2s/R = 0.5% of the area; the reference is the middle of that band; invalid: every element of a valid mesh has positive volume
- **[cdt-stepped-block](../tests/oracle/cdt-stepped-block/)** (theory): Constrained Delaunay mesh of a stepped block: exact volume, valid elements. Source: mesh invariants: a tetrahedralization of a polyhedron fills its volume exactly (Si, TetGen paper ACM TOMS 41(2) 2015 for the definition of a CDT; Diazzi et al., ACM TOG 42(6) 2023); the volume is 60·40·10 + 40·40·10 + 20·40·10 − 10·10·10. Tolerances — volume: a planar boundary is tessellated exactly and the constrained Delaunay mesh fills it exactly: only rounding; invalid: every element of a valid mesh has positive volume; undetermined: a linear tetrahedron's sign is exact
- **[explicit-bars-collision](../tests/oracle/explicit-bars-collision/)** (theory): Two identical elastic bars colliding (explicit contact). Source: One-dimensional elastic impact of equal bars: contact for 2L/c, interface force ρcAv₀/2, exchange of velocities, no loss of energy; Graff, Wave Motion in Elastic Solids, Dover 1991, §2.1–2.3; Johnson, Impact Strength of Materials, Arnold 1972, §1.6. Tolerances — duration: the penalty springs at the interface delay the release by a few element transit times (about 1% of 2L/c with 200 elements per bar); force: the plateau is ρcAv₀/2 to 0.01%; the peak is the plateau plus the ringing behind the discrete wave front, a few percent; v_a: the striker stops on average (its kinetic energy is under 0.01% of the start's, see ke); its far end node keeps the ringing of the discrete release front, a few percent of v₀; v_b: the struck bar leaves at v₀ on average; its far end node keeps the ringing of the discrete wave fronts, a few percent; ke: an elastic impact keeps the kinetic energy; the quadratic bulk viscosity at the compression fronts and the vibration left in the bars take a fraction of a percent; contact_energy: the penalty springs give back what they took; the trapezoidal work of a spring that engages between increments drifts by far less than 0.1%
- **[explicit-contact-patch](../tests/oracle/explicit-contact-patch/)** (theory): Contact patch test: two blocks with non-matching meshes in uniaxial compression (explicit contact). Source: The contact patch test: a contact discretisation must transmit a uniform pressure across a non-matching interface exactly; Taylor & Papadopoulos, On a patch test for contact problems in two dimensions, Nonlinear Computational Mechanics, Springer 1991, 690–702; Crisfield, Re-visiting the contact patch test, IJNME 48:435–449, 2000. Uniaxial stress between frictionless symmetry planes is uniform in both blocks. Tolerances — lower_corner: a uniform stress is an equilibrium of the discrete system (the integrated contact forces are the consistent nodal forces of a uniform pressure on both meshes); what is left is the ringing of the loading, a hundred wave transits slow; lower_centre: as for the corner element; lower_base: as for the corner element; upper_top: as for the corner element; force: the integrated contact pressure carries the whole load; the largest force of the run is the final one in a slow squeeze, up to the ringing; lateral: frictionless symmetry planes and a frictionless interface leave the blocks free to expand sideways; the non-matching interface must not hold them
- **[explicit-sliding-block-contact](../tests/oracle/explicit-sliding-block-contact/)** (theory): Block sliding to a stop on a deformable plate, friction decaying with the slip rate (explicit contact). Source: A rigid block launched at v₀ with friction μ(v) = μk + (μs − μk) e^(−d v) decelerates at g μ(v); it travels ∫₀^v₀ v dv / (g μ(v)) (Simpson's rule, 200 000 intervals) and stops after [v₀ + ln((μk + (μs − μk) e^(−d v₀))/μs)/d]/(g μk) = 1.2001; Meriam & Kraige, Engineering Mechanics: Dynamics, §3/5; the exponential decay law as in Oden & Martins, CMAME 52:527–634, 1985. Tolerances — distance: the block bounces on the penalty springs and the plate under it shears elastically, so the normal force and the slip rate it feels vary by a little around their rigid-body values; velocity: the block sticks; what is left is its elastic vibration, under 1% of v₀
- **[explicit-sliding-block-wall](../tests/oracle/explicit-sliding-block-wall/)** (theory): Block sliding to a stop on a rigid wall with Coulomb friction (explicit). Source: A rigid block launched at v₀ on a horizontal plane with Coulomb friction μ decelerates at μg and stops after v₀/(μg) at v₀²/(2μg), its kinetic energy all dissipated by friction; Meriam & Kraige, Engineering Mechanics: Dynamics, §3/5 (work and energy). Tolerances — distance: the wall's friction impulses are exact Coulomb impulses; the block's elastic vibration from the sudden gravity and the friction moment move the node by a fraction of a percent; velocity: the block sticks; what is left is its elastic vibration, under 1% of v₀; dissipated: the kinetic energy goes into friction; the vibration and the work of gravity as the block settles add or take a fraction of a percent
- **[filleted-bracket-fillet-stress](../tests/oracle/filleted-bracket-fillet-stress/)** (theory): Filleted L-bracket under a side load: the peak von Mises stress on the R6 fillet, fine tet10 mesh. Source: mesh convergence of the finite element solution (P. J. Roache, Verification and Validation in Computational Science and Engineering, Hermosa, 1998, ch. 5): the bracket has no closed-form stress; the reference is the mesh-independent peak of a four-level study of quadratic tetrahedral meshes refined by √2 in size and in curvature resolution (README.md); equilibrium. Tolerances — fillet_peak: the four-level study gives 213.3, 210.6, 214.3, 213.3 MPa (2k to 13.5k elements): the bending stress is converged across the fillet, and the peak nodal value moves only with which of the fillet's tessellation lines (fixed angles, through every level) carries the largest node, by under 2%; reaction: equilibrium holds to rounding
- **[filleted-bracket-fillet-stress-coarse](../tests/oracle/filleted-bracket-fillet-stress-coarse/)** (theory): Filleted L-bracket under a side load: the peak von Mises stress on the R6 fillet, coarse tet10 mesh. Source: mesh convergence of the finite element solution (P. J. Roache, Verification and Validation in Computational Science and Engineering, Hermosa, 1998, ch. 5): the bracket has no closed-form stress; the reference is the mesh-independent peak of a four-level study of quadratic tetrahedral meshes refined by √2 in size and in curvature resolution (README.md); equilibrium. Tolerances — fillet_peak: the four-level study gives 213.3, 210.6, 214.3, 213.3 MPa (2k to 13.5k elements): the bending stress is converged across the fillet, and the peak nodal value moves only with which of the fillet's tessellation lines (fixed angles, through every level) carries the largest node, by under 2%; reaction: equilibrium holds to rounding
- **[free-beam-frequencies](../tests/oracle/free-beam-frequencies/)** (theory): Natural frequencies of a free beam: rigid-body modes and the first bending mode. Source: Euler–Bernoulli free–free beam, β₁L = 4.7300; Timoshenko, Young and Weaver, Vibration Problems in Engineering, 4th ed., Wiley 1974, §5.3. Tolerances — rigid_6: a free body has six zero frequencies; numerical rigid-body frequencies below 10⁻³ of the first elastic one (eigenvalues below 10⁻⁶ of it) are rounding of the shifted solve; f7: Euler–Bernoulli neglects shear and rotary inertia, about 0.8% at L/h = 20 for the free–free mode; mass: the mass matrix integrates the density exactly
@@ -259,6 +280,7 @@ Reference values already cited; each case gets its recipe when the capability it
| Case | Kind | Problem | Needs | Reference values | Source |
|---|---|---|---|---|---|
| [cylinder-channel-2d1](../tests/oracle/cylinder-channel-2d1/) | benchmark | Flow around a cylinder, steady 2D-1 (Re = 20) | lattice Boltzmann CFD (M12) | drag coefficient (published interval 5.57–5.59) = 5.58; lift coefficient (interval 0.0104–0.0110) = 0.0107 | Schäfer and Turek, 'Benchmark computations of laminar flow around a cylinder', Notes on Numerical Fluid Mechanics 52 (1996) 547–566, Table 4 (reference intervals) |
| [explicit-hertz-spheres](../tests/oracle/explicit-hertz-spheres/) | theory | Two elastic spheres in a head-on collision: Hertz's force and contact duration (explicit contact) | a graded sphere mesh from commands (a cubed-sphere hex mesher, or tet refinement towards a point); until then the explicit crate's tests `spheres_collide_as_hertz_says` (a graded cubed-sphere quarter of each sphere, 27 648 hex8: peak force +2.3%, duration −0.4%) and its coarse twin in the main gate check this case on a mesh generated in code | the largest contact force, two steel spheres R = 10 mm (E = 210 GPa, ν = 0.3, ρ = 7.85 t/m³) meeting at 1 m/s (N) = 1005.4; the contact duration (s) = 6.0163e-5 | Hertz's quasi-static impact: with R* = R/2, m* = m/2, E* = E/(2(1 − ν²)), the approach reaches δ = (15 m* v²/(16 E* √R*))^(2/5), the force (4/3) E* √R* δ^(3/2), and the contact lasts 2.9432 δ/v; Hertz, J. reine angew. Math. 92:156–171, 1882; K. L. Johnson, Contact Mechanics, Cambridge 1985, §11.4 |
| [lid-driven-cavity-re100](../tests/oracle/lid-driven-cavity-re100/) | benchmark | Lid-driven cavity, Re = 100 | lattice Boltzmann CFD (M12) | u/U at y = 0.4531 on the vertical centreline = -0.2109 | Ghia, Ghia and Shin, Journal of Computational Physics 48 (1982) 387–411, Table I (u along the vertical centreline) |
| [mh-twisted-beam](../tests/oracle/mh-twisted-beam/) | benchmark | MacNeal–Harder twisted beam | shell elements (M8) or mapped blocks with helical edges | tip displacement along the in-plane load = 0.005424; tip displacement along the out-of-plane load = 0.001754 | MacNeal and Harder, 'A proposed standard set of problems to test finite element accuracy', Finite Elements in Analysis and Design 1 (1985) 3–20, Fig. 6 (p. 8), Table 3 (p. 10) |
| [nafems-le11](../tests/oracle/nafems-le11/) | benchmark | NAFEMS LE11 solid cylinder/taper/sphere under a temperature field | thermal loads (M8 heat transfer) | σ_zz at A = -105 | NAFEMS, The Standard NAFEMS Benchmarks, TNSB Rev. 3, October 1990, test LE11 (target σ_zz = −105 MPa at A) |
+2 -2
View File
@@ -55,7 +55,7 @@ products are run, no documentation text is copied). Status: **done**, **started*
| Model | Steps: linear static, frequency; output presets | M3 | | done |
| Model | Steps: nonlinear static, explicit dynamics, heat transfer; amplitudes | M7–M8, M15 | | started (nonlinear static with or without nonlinear geometry, increments, tolerances and a load path (cyclic loading), written to Abaqus `*STEP, NLGEOM` and LS-DYNA implicit (the load path as LS-DYNA's curve; refused by Abaqus for now), refused by Nastran; explicit dynamics; heat transfer; amplitudes per load planned) |
| Interaction | Tie between non-matching meshes | M7 | | planned |
| Interaction | Contact (general and pairs), friction, automatic pair detection | M7 | | planned |
| Interaction | Contact (general and pairs), friction, automatic pair detection | M7, M10 | | started (explicit: pairs, general and self contact, segment to segment with a penalty that keeps the time increment, Coulomb friction with exponential decay, friction on rigid walls, `interaction.contact.find`, Abaqus and LS-DYNA contact keywords; implicit contact in M7) |
| 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 |
@@ -64,7 +64,7 @@ products are run, no documentation text is copied). Status: **done**, **started*
| 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, wedge6, hex8, hex20; 2D plane stress, plane strain and axisymmetric tri3, tri6, quad4 (full, incompatible modes), quad8 (full, reduced); quad4/tri3 MITC shells and Timoshenko beams with profiles, mixed with solids; reference points, kinematic and distributing couplings, moments; centrifugal loads) |
| Solve | Own nonlinear implicit solver: Newton–Raphson with line search and automatic increments, total Lagrangian solids and 2D elements, mixed u–p at finite strain, follower pressure | M15 | yes | started (solids, plane strain, axisymmetric; St Venant–Kirchhoff, neo-Hookean and J2 plasticity (Simo's exponential return map at finite strain, radial return at small strain, consistent tangents, the return shared with explicit dynamics); verified by the elastica, tube inflation, patch and objectivity tests, uniaxial tension to large strain, Hill's thick cylinder, a cantilever's collapse and the Bauschinger effect; Mooney–Rivlin and Yeoh; thermal strain at finite and small strain; a symmetric indefinite LDLᵀ factorization with inertia, Newton through indefinite tangents (hybrid elements at ν = 0.4999 under prescribed displacement); shells, contact, buckling, arc-length next) |
| Solve | Own explicit dynamics solver (central differences, one-point hex8 with hourglass control, nodal-pressure tet4, bulk viscosity, energy balance), verified against analytic wave and impact solutions | M10 | yes | started (X1 core and X2: large deformation, objective rates, J2 and Johnson–Cook plasticity, damage, erosion; contact planned) |
| Solve | Own explicit dynamics solver (central differences, one-point hex8 with hourglass control, nodal-pressure tet4, bulk viscosity, energy balance), verified against analytic wave and impact solutions | M10 | yes | started (X1 core and X2: large deformation, objective rates, J2 and Johnson–Cook plasticity, damage, erosion; X3: deformable contact and friction, verified by bar collision, sliding blocks, the contact patch test and Hertz) |
| 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 |
+40
View File
@@ -1246,3 +1246,43 @@ update are written from (cited again in the module docs):
34(1):82–109, 1992.
- Iterative refinement: N. J. Higham, *Accuracy and Stability of Numerical Algorithms*, 2nd ed.,
SIAM 2002, §12.2.
## Part Q: Contact and friction (explicit), as implemented
The papers and books `fieldcraft_fem::contact` and `fieldcraft_explicit::contact` are written
from (cited again in the module docs); docs/fem.md describes the formulation.
- Closest point on a triangle by its Voronoi regions: C. Ericson, *Real-Time Collision
Detection*, Morgan Kaufmann 2005, §5.1.5; on a bilinear quadrilateral by Newton's method on the
stationarity conditions, projected on the parameter square: the local search of node-to-segment
contact, J. O. Hallquist, G. L. Goudreau, D. J. Benson, CMAME 51:107–137, 1985 (A5.1), and P.
Wriggers, *Computational Contact Mechanics*, 2nd ed., Springer 2006, §4.1.
- Global search by bucket sorting into a uniform grid: D. J. Benson, J. O. Hallquist, CMAME
78:141–163, 1990 (A5.2). We chose a grid over the BVH of A5.4: one pass per increment, memory
bounded by caps whatever the mesh, candidates in face order (determinism); the cell grows when a
few huge faces would blow the entry cap.
- Segment-to-segment integration (projection on the secondary face's plane, clipping,
sub-triangle quadrature): M. A. Puso, T. A. Laursen, *A mortar segment-to-segment contact
method for large deformation solid mechanics*, CMAME 193:601–629, 2004; with the penalty applied
at the integration points, K. A. Fischer, P. Wriggers, Comput. Mech. 36:226–244, 2005; polygon
clipping, I. E. Sutherland, G. W. Hodgman, Commun. ACM 17(1):32–42, 1974. Chosen over
node-to-segment because the latter fails the contact patch test on non-matching meshes (R. L.
Taylor, P. Papadopoulos, in *Nonlinear Computational Mechanics*, Springer 1991, 690–702; M. A.
Crisfield, IJNME 48:435–449, 2000), which our first node-to-segment version showed too (12%
spread of σ_zz in the patch test, 0.1% now).
- Penalty from the masses and the stable increment (the "soft constraint" idea: J. O. Hallquist,
*LS-DYNA Theory Manual*, LSTC 2006, the contact chapter's soft-constraint option; the bound is ours: Gershgorin's row sums of the
integrated contact stiffness with the node's directional area, added to the element
frequencies by Weyl's inequality).
- Friction by a regularised (penalty) return map: P. Wriggers, *Computational Contact
Mechanics*, §5.2 and §10.3; J. C. Simo, T. A. Laursen, Comput. Struct. 42(1):97–116, 1992;
rate-dependent coefficients reviewed by J. T. Oden, J. A. C. Martins, CMAME 52:527–634, 1985.
The exponential decay μ = μ_k + (μ_s − μ_k) e^{−d γ̇} is the form the LS-DYNA and Abaqus
manuals document, so the decks carry it unchanged.
- Kinematic rigid walls with Coulomb impulses: T. J. R. Hughes et al., CMAME 8(3):249–276, 1976
(A5.5), the tangential impulse capped at μ times the normal one.
- Verification: the impact of equal bars, K. F. Graff, *Wave Motion in Elastic Solids*, Dover
1991, §2.1–2.3, and W. Johnson, *Impact Strength of Materials*, Arnold 1972, §1.6; Hertz's
impact of spheres, H. Hertz, J. reine angew. Math. 92:156–171, 1882, and K. L. Johnson,
*Contact Mechanics*, Cambridge 1985, §11.4; the sliding block, any dynamics text (J. L. Meriam,
L. G. Kraige, *Engineering Mechanics: Dynamics*, §3/5).
+3 -1
View File
@@ -59,7 +59,9 @@ cargo xtask oracle --quick # skip cases marked "slow"
"known_failure": "optional: why FieldCraft misses the reference today"}]}
```
A measure reads a JSON pointer either from a recipe step's output (`"from": "<id>"`) or from a
command run after the recipe (`"command"`, `"params"`); an optional `"scale"` multiplies it.
command run after the recipe (`"command"`, `"params"`); an optional `"scale"` multiplies it, and
an optional `"over"` (a measure of its own) divides it by another number of the same run, for
ratios such as the stress in one element over the stress in another.
A tolerance is `relative` (of the reference), `absolute`, both, or `"exact": true`. A pending
case cites its reference values (or `null` until transcribed) and has no recipe yet.
- `fixture.json` holds each passing quantity's accepted `value` and its `band`