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 <noreply@anthropic.com>
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

+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.