Files
OneCAD-Simulation/crates/explicit/src/result.rs
T
jyvikoandClaude Opus 5.5 50764def18 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 <[email protected]>
Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
2026-10-13 20:52:57 -04:00

127 lines
4.9 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! What an explicit dynamic run keeps: histories sampled at the history interval and field
//! frames at the output interval.
use serde::Serialize;
use crate::elements::Failure;
/// The energy account at one time (Belytschko, Liu, Moran, Elkhodary 2014, §6.2.3). The works of
/// the internal and external forces are integrated with the trapezoidal rule over each
/// increment's displacement; the constraints' with their impulses (see [`crate::integrate`]).
#[derive(Debug, Clone, Copy, Default, PartialEq, Serialize)]
pub struct Energies {
/// ½ vᵀ M v.
pub kinetic: f64,
/// Work of the material stresses: the strain energy for an elastic material.
pub internal: f64,
/// Work of the hourglass forces (stored in the stiffness form, dissipated in the viscous one).
pub hourglass: f64,
/// Work of the bulk viscosity (dissipated).
pub viscous: f64,
/// Work of the loads.
pub external: f64,
/// Work of the boundary conditions and rigid walls on the model.
pub constraint: f64,
/// Plastic work: the part of `internal` dissipated by plastic flow.
pub plastic: f64,
/// Internal energy of the eroded elements when they eroded (part of `internal`).
pub eroded: f64,
/// kinetic + internal + hourglass + viscous − external − constraint − the initial kinetic
/// energy: zero when energy is conserved.
pub balance: f64,
}
impl Energies {
/// The balance relative to the largest energy in the account.
pub fn relative_error(&self, initial_kinetic: f64) -> f64 {
let scale = [initial_kinetic, self.kinetic, self.internal + self.hourglass + self.viscous, self.external.abs(), self.constraint.abs()]
.into_iter()
.fold(0.0, f64::max);
if scale > 0.0 { self.balance.abs() / scale } else { 0.0 }
}
}
/// The fields at one time. Vectors that the step's output does not request are empty.
#[derive(Debug, Clone, PartialEq)]
pub struct Frame {
pub time: f64,
/// Per node in [`ExplicitResult::nodes`] order.
pub displacement: Vec<[f64; 3]>,
pub velocity: Vec<[f64; 3]>,
/// Per element in [`ExplicitResult::elements`] order (one-point elements: one value each):
/// xx, yy, zz, xy, xz, yz, engineering shear strains.
pub stress: Vec<[f64; 6]>,
/// The accumulated strain increments (small strain: the strain; large deformation: the
/// integral of the rate of deformation, rotated with the material).
pub strain: Vec<[f64; 6]>,
/// Per element, with stress output in a model with plasticity: equivalent plastic strain,
/// damage and temperature.
pub plastic_strain: Vec<f64>,
pub damage: Vec<f64>,
pub temperature: Vec<f64>,
/// Per element, with stress output: whether it has eroded.
pub failed: Vec<bool>,
}
/// An element removed from the analysis.
#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
pub struct ErodedElement {
pub label: u32,
pub time: f64,
pub failure: Failure,
/// Its internal energy (stress work) when it eroded.
pub internal_energy: f64,
}
/// Quantities sampled through the run.
#[derive(Debug, Clone, Default, PartialEq)]
pub struct History {
pub time: Vec<f64>,
/// The time increment taken at each sample.
pub increment: Vec<f64>,
pub energies: Vec<Energies>,
/// Total momentum M v.
pub momentum: Vec<[f64; 3]>,
/// Sum of the forces the boundary conditions and rigid walls exert on the model.
pub constraint_force: Vec<[f64; 3]>,
/// The nodes with histories, and per sample their displacement and velocity (in this order).
pub nodes: Vec<u32>,
pub displacement: Vec<Vec<[f64; 3]>>,
pub velocity: Vec<Vec<[f64; 3]>>,
}
/// An element that limits the stable time increment.
#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
pub struct ControllingElement {
pub label: u32,
/// Its critical increment at rest (no bulk viscosity), before the scale factor.
pub increment: f64,
}
/// The result of an explicit dynamic step.
#[derive(Debug, Clone, PartialEq)]
pub struct ExplicitResult {
pub step: String,
/// Node labels with degrees of freedom, sorted.
pub nodes: Vec<u32>,
/// Element labels, sorted.
pub elements: Vec<u32>,
pub frames: Vec<Frame>,
pub history: History,
/// The elements with the smallest critical increments (at most ten), smallest first.
pub controlling: Vec<ControllingElement>,
/// The first time increment taken (the scale times the smallest critical increment).
pub initial_increment: f64,
pub increments: u64,
/// The time reached: the step's end time unless the run stopped at the increment cap.
pub time: f64,
pub completed: bool,
pub total_mass: f64,
/// The energy account at the end.
pub energy: Energies,
pub initial_kinetic: f64,
/// Elements eroded during the run, in the order they eroded.
pub eroded: Vec<ErodedElement>,
pub warnings: Vec<String>,
}