CalculiX Nonlinear Analysis (structures/fem/calculix-nonlinear)
Use when the task is nonlinear finite element statics in the CalculiX (ccx) style: state-dependent stiffness, Newton-Raphson iteration, load stepping, and convergence verdicts.
Domain quick reference
- A nonlinear ccx static run applies when the linear assumption breaks: the stiffness of the structure depends on its own state.
- Geometric nonlinearity (large displacement) and material nonlinearity (plasticity) both appear as a state-dependent stiffness; the scalar model is a bar with k(u) = k0 * (1 + alpha*u).
- The equilibrium residual is r(u) = k(u)u - F = k0 * (u + alphau*2) - F; the tangent stiffness is kt(u) = dr/du = k0 * (1 + 2alpha*u).
- Newton-Raphson updates u_{n+1} = u_n - r(u_n)/kt(u_n) until abs(r) <= tolerance (converged) or the iteration budget is spent (not converged).
- Load stepping splits the total load into equal increments; each increment iterates from the previous converged state, mirroring a nonlinear run ramping the load.
Workflow
- Validate the solver inputs (positive k0, non-negative alpha, positive tolerance, at least one load step).
- Solve the equilibrium by Newton-Raphson, with the load applied in load_steps equal increments.
- Read the converged displacement, the total iteration count, and the final residual norm.
- Check the convergence verdict: residual norm <= tolerance means converged; exhausting the budget means not-converged.
- Compare against the closed-form root where available (u = (-1 + sqrt(1 + 4alphaF/k0)) / (2*alpha) for alpha > 0).
Pitfalls
- Applying the whole load in one increment when the increment count matters for convergence (stepping accumulates the applied load).
- Declaring convergence from the iteration count instead of the residual norm.
- Dividing by a zero tangent stiffness inside an increment; the solver must abort that increment cleanly.
- Forgetting that a negative discriminant means no real root.
Behavior contract (gate 3)
The nonlinear solver logic is exercised by the gate 3 contract test: scripts/test_calculix_nonlinear.py against scripts/calculix_nonlinear_logic.py (stdlib unittest, offline). Run:
python3 scripts/test_calculix_nonlinear.py