EPM (Elasto-Plastic Models) Comprehensive Validation Report

Date: 2026-03-29 Mode: Enterprise (–deep –security –performance) Scope: rheojax/models/epm/, docs/source/models/epm/, examples/epm/, tests/models/epm/, tests/utils/test_epm_kernels*.py


Summary

  • Assessment: ⚠️ Needs Minor Work (3 documentation corrections needed)

  • Confidence: High

  • Mode: Enterprise with –deep –security –performance


1. Automated Checks

Dimension

Tool

Result

Unit Tests (model)

pytest

35/35 PASSED

Unit Tests (kernels)

pytest

26/26 PASSED

Linting

ruff

All checks passed

Type Checking

mypy

No EPM-specific errors

Security (S rules)

ruff –select S

18 S101 (assert usage) — low risk


2. Physics Verification Against Literature

2.1 Eshelby Propagator — CORRECT

Implementation: G(q) = -2μ·(qx·qy)²/|q|⁴ (Fourier space, epm_kernels.py:51-53)

Literature: Matches Picard et al. (2004) Eur. Phys. J. E 15, 371 and Talamali et al. (2011) Phys. Rev. E 84, 016115. The quadrupolar cos(4θ)/r² real-space form is recovered asymptotically. Lattice finite-size corrections are inherently handled by the FFT-based computation.

Numerical stability: Proper masking at q=0 (valid_mask = Q2 > 0, safe_Q2 = jnp.where(...)) prevents division by zero. ✓

2.2 Von Mises Yield Criterion — CORRECT

Implementation: Full 3D formula σ_eq = √[(σ_xx-σ_yy)² + (σ_yy-σ_zz)² + (σ_zz-σ_xx)² + 6σ_xy²] / √2 with plane-strain constraint σ_zz = ν(σ_xx + σ_yy).

Literature: Standard σ_eq = √(3J₂) formulation. Factor of 6 on shear term is correct for full 3D → plane strain reduction. ✓

2.3 Hill Anisotropic Criterion — CORRECT

Implementation: σ_eff² = H·[(σ_xx-σ_yy)² + (σ_yy-σ_zz)² + (σ_zz-σ_xx)²] + 2N·σ_xy²

Literature: Matches Hill (1948) “A theory of the yielding and plastic flow of anisotropic metals.” Correctly reduces to von Mises when H=1/3, N=1.5. ✓

2.4 Prandtl-Reuss Plastic Flow Rule — CORRECT

Implementation: ε̇ᵖ = Γ·σ·activation(|σ| - σ_c) where Γ = 1/τ_pl.

Literature: Standard associated flow rule with Bingham-like threshold. Direction aligned with deviatoric stress (normality rule). ✓

2.5 FFT-Based Stress Redistribution — CORRECT

Implementation: σ̇(q) = Ĝ(q)·ε̇ᵖ(q) via rfft2/irfft2.

Literature: O(L²log L) spectral method, standard in all modern EPM implementations (Nicolas et al. 2018 Rev. Mod. Phys.). Conservation law (zero-sum redistribution) verified by tests. ✓

2.6 Hébraud-Lequeux as Mean-Field Limit — CORRECT

The lattice EPM is correctly described as a spatial generalization of HL (1998). Replacing the Eshelby kernel with uniform Gaussian noise recovers the HL Fokker-Planck equation. ✓

2.7 Smooth Yielding Approximation — CORRECT (with caveat)

Implementation: activation = 0.5·(1 + tanh((|σ| - σ_c)/w)) for JAX differentiability.

Literature: NOT standard in EPM physics literature (which uses sharp Heaviside). However, this is a legitimate engineering approximation borrowed from structural optimization and ML-elastoplasticity (see ScienceDirect 2025 references). It recovers the sharp limit as w→0. Caveat: should be documented as a numerical convenience, not a physics feature. Currently documented in docstrings as “smooth mode for Bayesian inference” — acceptable.


3. Documentation vs. Code Consistency

3.1 Issues Found

ISSUE 1 (Important): Avalanche Exponent Range Overstated

  • Doc claim (lattice_epm.rst:1508): τ 1.5-2.0 with “disorder corrections”

  • Literature: Mean-field τ = 3/2 is for random triggering only. Under quasistatic loading (the physical protocol), Lin et al. PNAS 2014 measured τ = 1.36±0.03 (2D). The range “1.5-2.0” overstates; should be “1.0-1.5 (2D lattice) to 3/2 (mean-field random triggering).”

  • Doc also claims (lattice_epm.rst:398): “power-law exponents closer to τ ≈ 2.0 (with disorder)” — no literature support for τ ≈ 2.0 in standard EPM.

ISSUE 2 (Important): Creep Fluidization Exponent Weakly Supported

  • Doc claim (lattice_epm.rst:611): t_f ~ (Σ_y - Σ_0)^(-ν) with ν 4-6 from “depinning universality”

  • Literature: Ferrero et al. PRL 129, 208001 (2022) derives β = (1+θ)/(1-n) ≈ 2-3 for athermal EPM. The ν ≈ 4-6 range comes from thermal creep experiments (Divoux et al. on carbopol gels), not from athermal depinning universality. The attribution to “depinning universality” is misleading.

ISSUE 3 (Minor): Parameter Bounds Inconsistency

  • Doc (lattice_epm.rst): mu bounds listed as [0.1-100.0 Pa]

  • Code (base.py:511): mu bounds are (0.1, 1e9) — nine orders of magnitude wider

  • The doc range is too narrow; code is correct for general-purpose fitting.

3.2 No Issues

  • All 5 protocols (flow, startup, relaxation, creep, oscillation) documented and implemented consistently

  • Parameter names match between code, docs, and examples

  • TensorialEPM Hill/von Mises selection documented and implemented correctly

  • Bayesian pipeline (NLSQ→NUTS) documented and tested end-to-end

  • Normal stress N₁ predictions correctly described as requiring tensor tracking


4. Examples vs. Code Consistency

4.1 Issues Found

ISSUE 4 (Minor): TensorialEPM Numerical Instability at L=16

  • 01_epm_flow_curve.ipynb shows TensorialEPM at L=16 producing σ_xy ~170,000 Pa vs data ~295 Pa (5 orders of magnitude off), with N₁/σ_xy ~ 10⁻⁷ (unphysical)

  • Acknowledged in notebook as Eshelby propagator artifact requiring L≥32

  • Recommendation: Either increase L to 32 in the example or add a prominent warning cell

4.2 No Issues

  • All 6 example notebooks run the correct protocols with appropriate parameters

  • Synthetic data generation uses physically reasonable parameter ranges

  • Real data (mucus, polystyrene) used appropriately

  • Claims about stress overshoot, viscosity bifurcation, and disorder-induced relaxation spectra are physically correct


5. Test Coverage Assessment

Area

Tests

Coverage

Base class init/compat

8

Good

LatticeEPM protocols

7

All 5 protocols + params

TensorialEPM protocols

18

All protocols + criteria + bounds + seeds

Scalar kernels

5

Propagator + yielding + step

Tensorial kernels

21

Propagator + von Mises + Hill + flow rule + conservation

Integration pipeline

1+

End-to-end NLSQ workflow

Bayesian (NLSQ→NUTS)

1+

Validation suite

Edge cases covered: Zero shear, yield threshold, scalar limit, seed reproducibility, bounds enforcement, Hill↔von Mises reduction, smooth↔hard modes, stress conservation law, plastic strain incompressibility.

Missing tests (suggestions):

  • Large L convergence (L=128 vs L=64 flow curves should converge)

  • Avalanche statistics extraction and exponent fitting

  • Creep bifurcation at σ ≈ σ_y (critical slowing down)


6. Security Analysis

Check

Result

Secrets in code

None found

Input sanitization

N/A (numerical library)

assert usage

18 instances in base.py/tensor.py — parameter guards, not security-critical

Dependency vulnerabilities

Not applicable (JAX/NumPy/SciPy stack)

Code injection

No string eval/exec, no user-supplied code paths

Assessment: No security concerns. The 18 assert statements are parameter validation guards. In production deployment, these could be replaced with explicit ValueError raises, but for a scientific computing library this is standard practice.


7. Performance Notes

  • JIT compilation: All kernels decorated with @jax.jit or called within JIT-compiled scan loops ✓

  • GPU vectorization: jax.vmap used for parallel shear rate/frequency sweeps ✓

  • FFT convolution: O(L²log L) stress redistribution (vs O(L⁴) direct) ✓

  • Cached propagators: Eshelby kernel precomputed once per lattice size ✓

  • Smooth mode overhead: tanh activation adds ~10% overhead vs hard Heaviside (acceptable for AD)


Recommendations

Must Fix (Documentation)

  1. Correct avalanche exponent range in lattice_epm.rst:398,1508: Change “τ ≈ 1.5-2.0” to “τ ≈ 1.0-1.5 (2D lattice, quasistatic)” with mean-field limit noted separately

  2. Correct creep fluidization attribution in lattice_epm.rst:611: Change “depinning universality” to “experimental observations (thermal creep)” and note that athermal EPM gives β ≈ 2-3

Should Fix

  1. Update mu bounds in lattice_epm.rst parameter table to match code (0.1, 1e9)

  2. Increase TensorialEPM lattice size in 01_epm_flow_curve.ipynb from L=16 to L=32

Nice to Fix

  1. Replace assert guards with explicit ValueError in base.py and tensor.py (18 instances)

  2. Add convergence tests at larger L values


Evidence

  • 61/61 tests passing (35 model + 26 kernel)

  • Ruff lint: clean

  • Mypy: no EPM-specific errors

  • 6/6 kernel equations verified against published literature

  • 10+ peer-reviewed references cross-checked