Repository navigation
Conversation
…ning) #15's acceptance criterion, deferred by #17: J2 with a tensor back-stress, unknowns {dgamma (scalar), beta (symmetric tensor)} solved as one coupled 7x7. Until now vector_newton had only ever been driven through synthetic systems with closed-form roots -- nothing had put it through a return map. The system, with eta = s_trial - dev(beta), q = sigma_eq(eta), N = (3/2)eta/q: R_g = q - 3G*g - sigma_y yield on the RETURNED state, because sigma_eq(s - beta) collapses to q - 3G*g R_B = beta - beta_n - (2/3)H*g*N Prager evolution Nothing pre-substitutes the radial-return simplification: N is taken from the current iterate, so it really does have to be solved coupled rather than decoupling into a scalar equation. The jacobian is derived rather than differenced -- dq/dB = -N and dN/dB = -((3/2)IIdev - N(x)N)/q, the same shape as j2's existing flow_normal_stress_derivative. Four tests. The coupled solve is checked against the CLOSED FORM, not against itself: for linear kinematic hardening the return is radial in the shifted space, so g = (q_tr - sigma_y)/(3G + H) exactly. That is an independent oracle. The returned state also has to sit on the shifted surface, sigma_eq(dev(sigma) - beta) == sigma_y. An elastic step must leave the state alone, and the branch that makes that true is not optional. Without it R_g = q - 3G*g - sigma_y still has a root for any trial state, and the solver finds it: measured on a step with q_tr = 2.10 against sigma_y = 50, it converged to g = -0.0148 with a spurious back stress of |beta| = 36.3. Negative plastic flow, reported as success. That is the bug this test exists for, and I hit it while writing the model rather than hypothesising it. The Bauschinger effect is what separates kinematic hardening from isotropic, so it gets its own test: in pure shear the elastic span between forward and reverse yield stays 2*sigma_y/sqrt(3) however far the forward loading went, because the surface translates instead of expanding. The fourth test exists because the first three cannot catch a jacobian error, and I checked rather than assumed -- flipping the sign of jacobian_g_B leaves all three passing. Newton converges to the root of the RESIDUAL; a wrong jacobian changes only the path. So the last test finite-differences the residual and compares every block. Mutation-verified across all four: jacobian_g_g, jacobian_g_B, jacobian_B_g and the 1.5 factor inside jacobian_B_B each fail it. Still open on #20: the consistent tangent through tangent_checker, which needs the strain_derivative wiring, and the two-surface model. 306/306.
|
Closing in favour of #162, a shipped J2 material with Armstrong-Frederick kinematic hardening on The review finding that decided it: linear Prager hardening is radial in the shifted space, and from the cold start the first Newton step is the radial return. With What carries over to #162: the closed-form Prager test and the |
First half of #20, which is #15's acceptance criterion deferred by #17: J2 with a tensor back-stress, unknowns
{Δγ (scalar), β (symmetric tensor)}solved as one coupled 7×7.Until now
vector_newtonhad only been driven through synthetic systems with closed-form roots. Nothing had put it through a return map — which matters, because the review round that produced #54 showed how much of its behaviour was unexercised.The system
With
η = s_tr − dev(β),q = σ_eq(η),N = (3/2)η/q:Nothing pre-substitutes the radial-return simplification —
Nis taken from the current iterate, so it genuinely has to be solved coupled rather than decoupling into a scalar equation. The Jacobian is derived rather than differenced:the same shape as j2's existing
flow_normal_stress_derivative.Four tests, and why each exists
Against the closed form, not against itself. For linear kinematic hardening the return is radial in the shifted space, so
Δγ = (q_tr − σ_y)/(3G + H)exactly — an independent oracle. The returned state must also sit on the shifted surface.The elastic branch is not optional, and I found that the hard way. Without it
R_γ = q − 3G·Δγ − σ_ystill has a root for any trial state, and the solver finds it. Measured on a step withq_tr = 2.10againstσ_y = 50: it converged toΔγ = −0.0148with a spurious back stress of|β| = 36.3. Negative plastic flow, reported as success. That was a real bug in my model, hit while writing it.The Bauschinger effect, because it's what separates kinematic from isotropic hardening: in pure shear the elastic span between forward and reverse yield stays
2σ_y/√3however far the forward loading went — the surface translates instead of expanding.A finite-difference check of the Jacobian, which exists because the first three cannot catch a Jacobian error. I verified that rather than assuming: flipping the sign of
jacobian_g_Bleaves all three passing, because Newton converges to the root of the residual and a wrong Jacobian changes only the path. Mutation-verified across every block:jacobian_g_gvaluejacobian_g_Bsignjacobian_B_gsignjacobian_B_B1.5 → 2.0Still open on #20
The consistent tangent through
tangent_checker(needs thestrain_derivativewiring —dR/dεfor both blocks), and the two-surface model. This PR is the first half; #20 stays open.306/306 pass.