Summary
A cube with a Norton creep law under a constant pressure, one *VISCO step with automatic incrementation. The stress is constant, so the creep rate is constant and CETOL never limits the increment: ccx increases it by 1.5 after every increment. Increments 1 to 12 converge in 2-3 iterations each, and the displacements are exact. In increment 13 (size 0.0865, a creep strain of about 17 elastic strains), ccx stops in the first iteration:
- exit status 255;
- the last lines ccx prints for increment 13 are “Factoring the system of equations using the symmetric spooles solver” and “Using 1 cpu for spooles.”;
- the only message is “matrix found to be singular”, in
spooles.out.
There is no cutback and no *ERROR. The same deck with *STEP, NLGEOM (routine incplas.f instead of incplas_lin.f) runs to the end of the step.
A tighter CETOL does not help: with CETOL=1.e-6 the deck stops in the same way at increment 19 (size 0.0837).
The stop depends on the creep exponent n and on r, the creep strain of one increment divided by the elastic strain q/E. I ran the same deck with other n and A (same creep rate), with the first and the largest increment set to a given r. n = 3 runs with increments of r = 150 and 200. n = 4 runs with r = 40; with a maximum of r = 50 the first increment is cut back and the run stops when the increment has grown back to r = 42. n = 5 runs with r = 15 and stops at r = 17. n = 8 and n = 10 stop already at r = 4 and r = 2, in increment 2: its start also extrapolates the elastic strain of increment 1. A long creep analysis with automatic increments reaches such an increment sooner or later, because the increments keep growing.
Version
ccx 2.23 (macOS arm64) and current master (537aa81, 2 Nov 2026) give the same output.
Already reported or fixed?
Not reported as far as I can find: no matching GitHub issue (open or closed) or pull request in Dhondtguido/CalculiX (searched 3 Nov 2026). Not fixed: incplas_lin.f and the increment start in nonlingeo.c are unchanged in this respect on master (537aa81).
The deck of Creep calculation and results (2021) ends this way on ccx 2.23 and master: in iteration 1 of increment 23 of its *VISCO step, at total time 0.997577E-03 (post 7 there reports the same stop time for ccx 2.17), with “matrix found to be singular” and exit 255. Its creep rate is far too high because ccx raises A·t^m to 1e-20 (reported separately), and that brings the increments to r ≈ 16 early.
Minimal input
norton_visco.inp:
** Unit cube C3D8, pressure q = 10 on the face x = 1 (symmetry BCs on x = 0, y = 0, z = 0).
** E = 2.e5, nu = 0.3. Norton creep (m = 0): A = 1.e-7, n = 5, creep rate A q^n = 0.01.
** One *VISCO step of 1 time unit, automatic increments starting at 0.001.
** Exact (small strain): u_x(x = 1) = q/E + 0.01 t = 5.e-5 + 0.01 t.
*NODE
1, 0., 0., 0.
2, 1., 0., 0.
3, 1., 1., 0.
4, 0., 1., 0.
5, 0., 0., 1.
6, 1., 0., 1.
7, 1., 1., 1.
8, 0., 1., 1.
*ELEMENT, TYPE=C3D8, ELSET=EALL
1, 1, 2, 3, 4, 5, 6, 7, 8
*NSET, NSET=X0
1, 4, 5, 8
*NSET, NSET=Y0
1, 2, 5, 6
*NSET, NSET=Z0
1, 2, 3, 4
*NSET, NSET=N7
7
*BOUNDARY
X0, 1, 1
Y0, 2, 2
Z0, 3, 3
*MATERIAL, NAME=MAT
*ELASTIC
2.e5, 0.3
*CREEP
1.e-7, 5., 0.
*SOLID SECTION, ELSET=EALL, MATERIAL=MAT
*STEP, INC=1000
*VISCO, CETOL=5.e-3
0.001, 1., 1.e-6, 1.
*DLOAD
1, P4, -10.
*NODE PRINT, NSET=N7
U
*END STEP
norton_visco_nl.inp is the same deck with *STEP, INC=1000, NLGEOM.
How to run
ccx norton_visco
ccx norton_visco_nl
Expected
The step runs to t = 1. If an increment is too large for the material routine, ccx cuts it back, as it does elsewhere (“increment size decrease requested by a material user routine (through pnewdt)”). Small-strain answer at node 7: u_x = 5e-5 + 0.01 t, 1.005e-2 at t = 1.
Actual
norton_visco: exit status 255. The .sta file:
1 11 1 2 0.114330E+00 0.114330E+00 0.384434E-01
1 12 1 2 0.171995E+00 0.171995E+00 0.576650E-01
Node 7 after increment 12: 7 1.769866E-03 -8.749328E-04 -8.749328E-04, matching 5e-5 + 0.01 t to 5 digits. Then “increment 13 attempt 1, increment size= 8.649756e-02, iteration 1” and the stop. spooles.out:
matrix found to be singular
norton_visco_nl: exit 0 after 17 increments; node 7 at t = 1: 7 1.001457E-02 -4.960035E-03 -4.960035E-03.
ccx 2.23 and master (537aa81) print the same numbers.
Where it goes wrong
The local Newton iteration for the creep increment in src/incplas_lin.f (master lines 255-361) starts from cop=0 and gives up after 15 iterations (lines 358-361):
if((iloop.gt.15).or.(cop.le.0.d0)) then
pnewdt=0.25d0
return
endif
It returns before it computes the tangent stiff (from line 399). The NLGEOM routine incplas.f has the same test at line 620, but there it restarts with a bracketing and bisection search for the root (lines 620-755) and gives up only after 100 more steps.
At the start of an increment, ccx extrapolates the displacements of the previous increment. With a constant creep rate this gives a trial stress of about q(1 + 1.15 r), with r the creep strain of the new increment in elastic strains. Far from the root, each Newton step lowers the stress by about a factor (1 - 1/n). So the number of iterations grows with ln(1 + 1.15 r)·n. A short script that repeats the loop of incplas_lin.f for this trial state needs more than 15 iterations above r ≈ 16 for n = 5. For n = 3, 4 and 5 that script puts the limit in the same ranges as the runs above (200-300, 40-50, 15-17). In the deck, increment 12 has r = 11.5 and increment 13 has r = 17.3.
That return happens in the results() call at the start of the increment (nonlingeo.c, master line 2230), whose stiffness (xstiff, resultsmech.f lines 974-977) is assembled for iteration 1. nonlingeo.c does not look at the cutback request (qa[2]) after that call. It only acts on it in checkconvergence after a solve. Here the solve fails first: the integration points that gave up have no valid tangent, and SPOOLES stops with exit(-1). When the same failure happens inside the iterations, the request works. With a first increment of 0.1 (r = 20) instead of 0.001, attempt 1 of increment 1 ends with “increment size decrease requested by a material user routine (through pnewdt)” and ccx retries with 0.025. That run then stops in the same way at increment 6 (size 0.084).
Fix
Either or both:
- give
incplas_lin.fthe fallback thatincplas.falready has (bracketing and bisection when Newton fails), or a better start value forcop; - in
nonlingeo.c, checkqa[2]after theresults()call at the start of an increment and cut back before the first solve.