Explicit X2: large deformation, J2 and Johnson-Cook plasticity, damage and erosion (M10)

- model: materials gain solver-neutral plastic (bilinear isotropic/kinematic,
  hardening table, Johnson-Cook with adiabatic heating), damage (Johnson-Cook
  D1-D5) and erosion (plastic strain); explicit steps gain nonlinear_geometry
  (default on) and stress_rate (jaumann | green_naghdi).
- fem: rotation (Hughes-Winget, Flanagan-Taylor), plasticity (radial return,
  capped bracketed Newton for Johnson-Cook, damage; the update takes the
  mechanical strain increment so thermal strains can be subtracted), closed-form
  hex8 gradients for deformed configurations.
- explicit: updated Lagrangian hex8/tet4, per-element material state, erosion
  with reported energy, plastic work in the energy account.
- solver: warns that the linear solver uses the elastic constants of plastic
  materials (results hash-identical).
- decks: Abaqus *PLASTIC (+ Johnson-Cook keywords), Nastran MATS1/TABLES1,
  LS-DYNA *MAT_PLASTIC_KINEMATIC / *MAT_PIECEWISE_LINEAR_PLASTICITY; what a
  format cannot express is reported as Unsupported.
- engine: model.material.plasticity, model.material.damage (catalogue ready),
  explicit element probe, eroded elements in the solve summary.

Step commits before the rebase onto the DOF framework: branch explicit-x2-steps.

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-13 20:52:57 -04:00
1 parent 4c0fcc80ad
commit 50764def18
38 files changed
+2839 -254

No files matched your search

+7 -4
View File
@@ -77,8 +77,11 @@ impl Bar {
}
}
m.add_set("end_face", Set { faces, ..Set::default() }).unwrap();
m.add_material("Mat", Material { elastic: Some(Elastic::Isotropic { young: YOUNG, poisson: 0.0 }), density: Some(DENSITY), fluid: None })
.unwrap();
m.add_material(
"Mat",
Material { elastic: Some(Elastic::Isotropic { young: YOUNG, poisson: 0.0 }), density: Some(DENSITY), ..Material::default() },
)
.unwrap();
let integration = if kind == ElementKind::Hex8 { Integration::Reduced } else { Integration::Full };
let formulation = Formulation { integration, ..Formulation::default() };
m.add_section("bar", Section { set: "all".into(), material: "Mat".into(), kind: SectionKind::Solid {}, formulation }).unwrap();
@@ -334,12 +337,12 @@ fn caps_and_unsupported_models_are_errors() {
assert!(solve_explicit(&full.model, None, &Limits::default()).unwrap_err().to_string().contains("not supported yet"));
let mut ortho = Bar::new(ElementKind::Tet4, 4, ExplicitDynamic::new(end));
let constants = Elastic::EngineeringConstants { young: [YOUNG; 3], poisson: [0.0; 3], shear: [YOUNG / 2.0; 3] };
ortho.model.replace_material("Mat", Material { elastic: Some(constants), density: Some(DENSITY), fluid: None }).unwrap();
ortho.model.replace_material("Mat", Material { elastic: Some(constants), density: Some(DENSITY), ..Material::default() }).unwrap();
assert!(solve_explicit(&ortho.model, None, &Limits::default()).unwrap_err().to_string().contains("orthotropic"));
let mut light = Bar::new(ElementKind::Tet4, 4, ExplicitDynamic::new(end));
light
.model
.replace_material("Mat", Material { elastic: Some(Elastic::Isotropic { young: YOUNG, poisson: 0.0 }), density: None, fluid: None })
.replace_material("Mat", Material { elastic: Some(Elastic::Isotropic { young: YOUNG, poisson: 0.0 }), density: None, ..Material::default() })
.unwrap();
assert!(solve_explicit(&light.model, None, &Limits::default()).is_err());
// A node behind its wall at the start.