Skip to content

About

Implicit return-mapping J2 plasticity in NumPy: Armstrong-Frederick kinematic + power-law isotropic hardening, thin-walled tube under nonproportional axial-torsion loading, load-history effects

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Repository files navigation

J2 Plasticity: Implicit Return Mapping

Rate-independent metal plasticity integrated the way finite-element codes do it at every integration point: a trial elastic step, a check of the yield function, and an implicit return to the yield surface. Two models, both in plain NumPy:

  • 1D with combined linear isotropic + linear kinematic hardening, under stress or strain control, with a time-step convergence study.
  • 3D J2 (von Mises) with Armstrong-Frederick nonlinear kinematic hardening and power-law isotropic hardening, under strain control, applied to a thin-walled tube in combined axial-torsion loading — the classic test for nonproportional cyclic plasticity.

Tube under sinusoidal axial and shear strain: axial loop, shear loop, phase plot

Run it

pip install numpy scipy matplotlib
python run_examples.py          # every figure below, ~1 minute
python j2_plasticity.py         # built-in physics checks

Tip

Both models are small classes with one integrate(path) method. To try your own material or loading, change the constructor arguments or hand integrate a different strain history — a (steps, 3, 3) array of strain tensors for the 3D model, a 1D array for the 1D model.

The algorithm

1D: combined linear hardening

Yield function $\phi = |\sigma - q| - (S_y + K\alpha)$, with backstress $q$ evolving as $\dot q = H,\dot\varepsilon^p$ and $\alpha$ the cumulative plastic strain. Each step: freeze the plastic variables, compute the trial state, evaluate $\phi_{trial}$. If it is positive the plastic increment that returns exactly to the yield surface has a closed form:

$$\Delta\lambda = \frac{\phi_{trial}}{H + K} \ \ (\text{stress control}), \qquad \Delta\lambda = \frac{\phi_{trial}}{E + H + K} \ \ (\text{strain control})$$
Stress-controlled cycling Time-step convergence

The middle panel shows the discipline of the scheme: $\phi = 0$ to machine precision on every plastic step and $\phi < 0$ during elastic unloading. The convergence plot shows first-order accuracy of backward Euler.

3D: Armstrong-Frederick + power-law isotropic hardening

$$\Phi = \sigma_{eq}(\mathbf S - \mathbf q) - \left[S_y + h\,\alpha^{n}\right], \qquad \sigma_{eq}(\boldsymbol\xi) = \sqrt{\tfrac{3}{2}\,\boldsymbol\xi : \boldsymbol\xi}$$ $$\dot{\boldsymbol\varepsilon}^p = \dot\lambda\,\mathbf N, \quad \mathbf N = \frac{3}{2}\frac{\mathbf S - \mathbf q}{\sigma_{eq}}, \qquad \dot{\mathbf q} = \tfrac{2}{3}\,C\,\dot{\boldsymbol\varepsilon}^p - \gamma\,\mathbf q\,\dot\lambda$$

The Armstrong-Frederick "dynamic recovery" term $-\gamma\mathbf q\dot\lambda$ makes the backstress saturate (at $2C/3\gamma$ in uniaxial tension), which is what produces realistic hysteresis loops and ratcheting.

Implicit update. Backward Euler on the backstress gives $\mathbf q_{n+1} = [\mathbf q_n + \tfrac{2}{3}C\Delta\lambda,\mathbf N]/(1+\gamma\Delta\lambda)$, and a short calculation shows the updated relative stress $\mathbf S_{n+1} - \mathbf q_{n+1}$ is parallel to

$$\boldsymbol\xi^*(\Delta\lambda) = \mathbf S_{trial} - \frac{\mathbf q_n}{1 + \gamma\Delta\lambda}$$

so the flow direction is known once $\Delta\lambda$ is, and the entire tensor update collapses to one scalar equation:

$$f(\Delta\lambda) = \sigma_{eq}(\boldsymbol\xi^*) - \left[3G + \frac{C}{1+\gamma\Delta\lambda}\right]\Delta\lambda - S_y - h\,(\alpha_n + \Delta\lambda)^n = 0$$

Important

This is solved with a bracketed root finder rather than Newton's method. The power-law term has derivative $\propto \alpha^{n-1}$, which is singular at $\alpha = 0$ for $n < 1$, so a bare Newton iteration on the first plastic step has to be special-cased (the original MATLAB did exactly that). Bracketing sidesteps the problem entirely and converges to $|\Phi| \sim 10^{-9}$ MPa on every plastic step.

Note

Stresses and strains are stored as 3×3 tensors, not 6-component Voigt vectors. This avoids the classic trap where a Euclidean norm of a Voigt vector under-counts the shear components by a factor of 2.

The thin-walled tube

A tube under axial strain $\varepsilon_{zz}$ and torsional shear $\varepsilon_{z\theta}$ has stress-free lateral surfaces, $\sigma_{rr} = \sigma_{\theta\theta} = 0$. The tube examples therefore use mixed control: the axial and shear strains are imposed while the two lateral strains are solved each step so the lateral stresses vanish (integrate(..., free_lateral=True)). Prescribing all other strains as zero instead — a common simplification in coursework — adds a large spurious hydrostatic stress ($K,\varepsilon_{zz}$, about 2.7 GPa here) to the axial component.

The headline figure shows an Inconel-like material (E = 210 GPa, ν = 0.26, $S_y$ = 980 MPa, n = 1/5.1, h = 300 MPa, C = 26 000 MPa, γ = 50) under $\varepsilon_{zz} = A\sin 2\pi t$, $\varepsilon_{z\theta} = (A/2)\sin\pi t$, $A = 4S_y/E$, for 2 s. The 2:1 frequency ratio makes the loading nonproportional: the butterfly-shaped shear loop and the phase plot wandering outside the initial yield ellipse are the signatures.

Load-history dependence

Ramp to the same final strains three ways — axial first then shear, shear first then axial, or both together:

Stress-strain curves for three load histories reaching the same final strain

History final $\sigma_{zz}$ (MPa) final $\tau_{z\theta}$ (MPa)
normal first, then shear 524 702
shear first, then normal 1353 116
simultaneous 1195 409

Same final strain state, stresses that differ by a factor of two and more: plasticity is path dependent, and the component loaded last carries most of the stress because the backstress has rotated toward it. This is why incremental integration along the actual history is necessary — a deformation-theory shortcut from final strains cannot get these numbers.

Files

plasticity1d.py     1D model (stress and strain control)
j2_plasticity.py    3D J2 model with AF + power-law hardening, tube loading programs
run_examples.py     regenerates every figure
figures/
matlab/             the original 2014 MATLAB scripts, kept for reference

References

  • J. C. Simo and T. J. R. Hughes, Computational Inelasticity, Springer, 1998 — the return-mapping framework.
  • P. J. Armstrong and C. O. Frederick, "A mathematical representation of the multiaxial Bauschinger effect," CEGB Report RD/B/N731, 1966.
  • J. L. Chaboche, "Constitutive equations for cyclic plasticity and cyclic viscoplasticity," Int. J. Plasticity 5, 247–302, 1989.

Author

Aiden Azarnoush — originally developed in MATLAB for a graduate plasticity course (2014); rewritten in Python.

License

MIT — see LICENSE.

About

Implicit return-mapping J2 plasticity in NumPy: Armstrong-Frederick kinematic + power-law isotropic hardening, thin-walled tube under nonproportional axial-torsion loading, load-history effects

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages