solver: J2 plasticity in nonlinear static steps, finite and small strain

Elements of a plastic material take the J2 material point: total Lagrangian
with nonlinear geometry, the small-strain loops without (elastic elements keep
their linear stiffness, so elastic results do not move). The plastic history is
committed per converged increment. Increments follow the step's load path,
ending at its points, the extrapolated predictor scaled by the change of the
load factor. Steps with path-dependent materials start an increment without a
predictor from the tangent predictor (the prescribed motion spread through the
converged tangent), and a first tangent that is not positive definite is a
cutback when the undeformed model's is. Refused by name: the Johnson-Cook rate
term (a static step has no time) and kinematic hardening at finite strain;
damage, erosion and adiabatic heating are left out with a warning. Results
carry the equivalent plastic strain at the integration points (solve.probe,
the step summary). LS-DYNA writes a load path as the step's curve; Abaqus
refuses it and a plastic deck of several general steps (Abaqus carries the
plastic state between them).

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 06:03:36 -04:00
1 parent 569b69c061
commit 17b2c837f2
11 files changed
+588 -64

No files matched your search

+5 -2
View File
@@ -61,6 +61,9 @@ pub struct ElementStress {
pub points: Vec<PointStress>,
/// Extrapolated to the element's nodes, in its node order.
pub nodal: Vec<[f64; 6]>,
/// The equivalent plastic strain at the integration points (nonlinear steps with a plastic
/// material; empty otherwise).
pub plastic_strain: Vec<f64>,
}
/// The motion and reaction of a coupled reference point: translations along X, Y, Z, then
@@ -431,7 +434,7 @@ pub fn solve_static(model: &Model, step: Option<&str>, limits: &Limits) -> Resul
*c += 1;
}
}
elements.push(ElementStress { label: e.label, kind: e.kind, points, nodal });
elements.push(ElementStress { label: e.label, kind: e.kind, points, nodal, plastic_strain: Vec::new() });
}
for t in &mesh.trusses {
let truss = t.truss()?;
@@ -448,7 +451,7 @@ pub fn solve_static(model: &Model, step: Option<&str>, limits: &Limits) -> Resul
*c += 1;
}
}
elements.push(ElementStress { label: t.label, kind: t.kind, points, nodal });
elements.push(ElementStress { label: t.label, kind: t.kind, points, nodal, plastic_strain: Vec::new() });
}
elements.sort_by_key(|e| e.label);
let (mut shells, mut beams) = (Vec::new(), Vec::new());