Plastic, creep or user material: segfault in *NO ANALYSIS, *BUCKLE, *COMPLEX FREQUENCY, a linear *STATIC after *FREQUENCY, and modal steps with S/RF output

Summary

A model whose material has *PLASTIC, *CREEP, *MOHR COULOMB, *DEFORMATION PLASTICITY or *USER MATERIAL crashes with a segmentation fault (exit status 139, no message) in these steps:

  • any *NO ANALYSIS step, also as the first step;
  • any *BUCKLE step, also as the first step;
  • a *STATIC step without NLGEOM after a *FREQUENCY step, a *STEP, PERTURBATION *STATIC step, and a *VISCO step after a *FREQUENCY step;
  • a *MODAL DYNAMIC or *STEADY STATE DYNAMICS step that writes stresses (*EL FILE S), reaction forces (*NODE PRINT RF, *NODE FILE RF) or contact output (*CONTACT FILE CDIS, *CONTACT PRINT CSTR); with *NODE FILE U only these steps run;
  • a *COMPLEX FREQUENCY, CORIOLIS step.

There are two exceptions, both in the material table below. A *BUCKLE step with the user material runs. With *DEFORMATION PLASTICITY, the *FREQUENCY step stops first, with an error message. The loads are far below yield, so the material stays elastic. The same decks run to the end when the material is elastic, elastic with *DEPVAR, or *HYPERELASTIC. A *FREQUENCY step of the plastic model runs as well.

In every case the backtrace ends in a material routine that reads a field nobody allocated, called through results() by the procedure routine: linstatic(), arpackbu(), dyna(), steadystate() or complexfreq(). These routines call the material routines (incplas_lin, mohrcoulomb, umat_abaqusnl_total, user materials through resultsmech), but they never allocate xstateini (the state variables at the start of the increment). linstatic.c allocates it only for contact. For user materials linstatic, steadystate and complexfreq also leave vini unallocated, and dyna leaves stiini and emeini unallocated. arpack.c (*FREQUENCY) allocates all of them, and its comment says what the state copy is for. That is why the frequency step runs.

All the cases have this one cause: the routines that ccx uses for linear steps evaluate the nonlinear material without the fields it needs. *NO ANALYSIS, *FREQUENCY, *BUCKLE and *COMPLEX FREQUENCY set iperturb(1)=0. That sends the *NO ANALYSIS step itself, and any later *STATIC or *VISCO step without NLGEOM, to linstatic(). A *STEP, PERTURBATION *STATIC step goes there too. *BUCKLE, *MODAL DYNAMIC, *STEADY STATE DYNAMICS and *COMPLEX FREQUENCY have their own routines.

Version

ccx 2.23 (macOS arm64). Source: master 9ba5d76 (16 Oct 2026).

Already reported or fixed?

Not reported: I found no matching GitHub issue (open or closed) or pull request in Dhondtguido/CalculiX, and no calculix.discourse.group topic (searched 21 Oct 2026). Not fixed: linstatic.c, arpackbu.c, dyna.c, steadystate.c and complexfreq.c still have no allocation of xstateini outside contact on master (9ba5d76).

Related:

Minimal input

plastic_buckle.inp is one C3D8 cube with an isotropic plastic material (yield 250), clamped at z = 0, and a buckling step with 1 N per top node:

*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=Z0
1, 2, 3, 4
*NSET, NSET=TOP
5, 6, 7, 8
*MATERIAL, NAME=STEEL
*ELASTIC
210000., 0.3
*PLASTIC
250., 0.
300., 0.1
*DENSITY
7.8E-9
*SOLID SECTION, ELSET=EALL, MATERIAL=STEEL
*BOUNDARY
Z0, 1, 3
*STEP
*BUCKLE
1
*CLOAD
TOP, 3, -1.
*END STEP

The elastic twin elastic_buckle.inp is the same deck without the two *PLASTIC data lines and the *PLASTIC card.

Other cases: replace the *STEP ... *END STEP block of plastic_buckle.inp with one of these

steps_na.inp:

*STEP
*NO ANALYSIS
*END STEP

steps_static_na.inp:

*STEP
*STATIC
*CLOAD
TOP, 3, -1.
*END STEP
*STEP
*NO ANALYSIS
*END STEP

steps_static_buckle.inp:

*STEP
*STATIC
*CLOAD
TOP, 3, -1.
*END STEP
*STEP
*BUCKLE
1
*CLOAD
TOP, 3, -1.
*END STEP

steps_freq.inp:

*STEP
*FREQUENCY
2
*END STEP

steps_freq_static.inp:

*STEP
*FREQUENCY
2
*END STEP
*STEP
*STATIC
*CLOAD
TOP, 3, -1.
*END STEP

steps_static_pert.inp:

*STEP
*STATIC
*CLOAD
TOP, 3, -1.
*END STEP
*STEP, PERTURBATION
*STATIC
*CLOAD
TOP, 3, -2.
*END STEP

steps_md_u.inp (steps_md_s.inp: *EL FILE / S instead of *NODE FILE / U; steps_md_rf.inp: *NODE PRINT, NSET=Z0 / RF instead):

*STEP
*FREQUENCY, STORAGE=YES
2
*END STEP
*STEP
*MODAL DYNAMIC
0.001, 0.01
*CLOAD
7, 1, 1.
*NODE FILE
U
*END STEP

steps_ssd_u.inp (steps_ssd_s.inp: *EL FILE / S instead; steps_ssd_rf.inp: *NODE FILE / U, RF instead):

*STEP
*FREQUENCY, STORAGE=YES
2
*END STEP
*STEP
*STEADY STATE DYNAMICS
10., 1000., 3
*CLOAD
7, 1, 1.
*NODE FILE
U
*END STEP

steps_cf.inp:

*STEP
*FREQUENCY, STORAGE=YES
4
*DLOAD
EALL, CENTRIF, 1.E4, 0., 0., 0., 0., 0., 1.
*END STEP
*STEP
*COMPLEX FREQUENCY, CORIOLIS
2
*DLOAD
EALL, CENTRIF, 1.E4, 0., 0., 0., 0., 0., 1.
*END STEP

steps_freq_visco.inp (with *CREEP, LAW=TIME / 1.E-12, 1., 0. in place of the *PLASTIC lines):

*STEP
*FREQUENCY
2
*END STEP
*STEP
*VISCO, CETOL=1.E-3
0.1, 1.
*CLOAD
TOP, 3, -1.
*END STEP

Other materials, in place of the three *PLASTIC lines (the user material is ccx’s built-in LIN_ISO_EL, linear elastic):

*PLASTIC, HARDENING=KINEMATIC / 250., 0. / 300., 0.1
*CREEP, LAW=TIME / 1.E-12, 1., 0.
*MOHR COULOMB / 30., 0. / *MOHR COULOMB HARDENING / 100., 0.
*DEFORMATION PLASTICITY / 210000., 0.3, 250., 10., 0.3
*DEPVAR / 2
*HYPERELASTIC, NEO HOOKE / 80000., 1.E-5
user material: *MATERIAL, NAME=LIN_ISO_EL / *USER MATERIAL, CONSTANTS=2 / 210000., 0.3
               (no *ELASTIC card; *SOLID SECTION ... MATERIAL=LIN_ISO_EL)

contact_md.inp: the plastic cube with an elastic block pressed on it (node-to-surface contact), a static step, a frequency step and a modal dynamic step with contact output. TYPE=SURFACE TO SURFACE crashes the same way.

*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.
9, 0., 0., 1.
10, 1., 0., 1.
11, 1., 1., 1.
12, 0., 1., 1.
13, 0., 0., 2.
14, 1., 0., 2.
15, 1., 1., 2.
16, 0., 1., 2.
*ELEMENT, TYPE=C3D8, ELSET=COL
1, 1, 2, 3, 4, 5, 6, 7, 8
*ELEMENT, TYPE=C3D8, ELSET=BLK
2, 9, 10, 11, 12, 13, 14, 15, 16
*NSET, NSET=Z0
1, 2, 3, 4
*NSET, NSET=BTOP
13, 14, 15, 16
*MATERIAL, NAME=STEEL
*ELASTIC
210000., 0.3
*PLASTIC
250., 0.
300., 0.1
*DENSITY
7.8E-9
*MATERIAL, NAME=EL
*ELASTIC
210000., 0.3
*DENSITY
7.8E-9
*SOLID SECTION, ELSET=COL, MATERIAL=STEEL
*SOLID SECTION, ELSET=BLK, MATERIAL=EL
*SURFACE, NAME=COLTOP
COL, S2
*SURFACE, NAME=BLKBOT
BLK, S1
*SURFACE INTERACTION, NAME=INT
*SURFACE BEHAVIOR, PRESSURE-OVERCLOSURE=LINEAR
1.E6
*CONTACT PAIR, INTERACTION=INT, TYPE=NODE TO SURFACE
BLKBOT, COLTOP
*BOUNDARY
Z0, 1, 3
BTOP, 1, 2
*STEP
*STATIC
*CLOAD
BTOP, 3, -10.
*END STEP
*STEP
*FREQUENCY, STORAGE=YES
2
*END STEP
*STEP
*MODAL DYNAMIC
0.001, 0.01
*CLOAD
15, 1, 1.
*CONTACT FILE
CDIS
*END STEP

How to run

ccx plastic_buckle; for the other cases, build the deck from the model part of plastic_buckle.inp and a steps block, then run it the same way.

Expected

The deck finishes with exit status 0, as the elastic twins do. elastic_buckle.inp prints the buckling factor 0.1122004E+05. In these steps the cube stays elastic: under the same load in a static step, the largest stress component is 4.5, against a yield stress of 250. Where ccx cannot handle the material in a step, the intended way to stop is an *ERROR message.

Actual

ccx plastic_buckle prints:

 STEP            1

 Buckling analysis was selected

 Decascading the MPC's

 Determining the structure of the matrix:
 Using up to 1 cpu(s) for setting up the structure of the matrix.
 number of equations
 12
 number of nonzero lower triangular matrix elements
 66

 Using up to 1 cpu(s) for the stress calculation.

and is then killed by SIGSEGV (exit status 139). There is no message, and the .dat file is empty.

Per case (plastic cube, exit status; elastic twin; the procedure routine in the backtrace):

steps *PLASTIC elastic crash in
*NO ANALYSIS 139 0 linstatic
*STATIC, *NO ANALYSIS 139 0 linstatic
*BUCKLE 139 0 arpackbu
*STATIC, *BUCKLE 139 0 arpackbu
*FREQUENCY 0 0
*FREQUENCY, *STATIC 139 0 linstatic
*STATIC, *STEP, PERTURBATION *STATIC 139 0 linstatic
*FREQUENCY, *VISCO (*CREEP) 139 0 linstatic
*FREQUENCY, *MODAL DYNAMIC with *NODE FILE U 0 0
same with *EL FILE S 139 0 dyna
same with *NODE PRINT RF 139 0 dyna
*FREQUENCY, *STEADY STATE DYNAMICS with *NODE FILE U 0 0
same with *EL FILE S 139 0 steadystate
same with *NODE FILE U, RF 139 0 steadystate
*FREQUENCY, *COMPLEX FREQUENCY, CORIOLIS 139 0 complexfreq
contact: *STATIC, *FREQUENCY, *MODAL DYNAMIC with *CONTACT FILE CDIS 139 0 dyna
same with *CONTACT PRINT CSTR 139 0 dyna
same as *STEADY STATE DYNAMICS with *CONTACT FILE CDIS 139 0 steadystate

Per material (exit status):

material *NO ANALYSIS *BUCKLE *FREQUENCY, *STATIC
*PLASTIC (isotropic or kinematic) 139 139 139
*CREEP 139 139 139
*MOHR COULOMB 139 139 139
*DEFORMATION PLASTICITY 139 139 201 (1)
*USER MATERIAL (LIN_ISO_EL) 139 0 139
elastic, elastic + *DEPVAR, *HYPERELASTIC 0 0 0

(1) The *FREQUENCY step stops first, with “*ERROR in umat_abaqusnl: negative eigenvalue of the Cauchy-Green tensor”. That is a different problem (reported separately).

The plastic material crashes in incplas_lin reading address 0x0 (epini=xstateini(1,iint,iel), incplas_lin.f line 72). Mohr-Coulomb crashes in mohrcoulomb, and deformation plasticity in umat_abaqusnl_total (copying xstateini into xstate). The user material crashes in resultsmech reading vini (address 0x8) or stiini (address 0x0 in dyna).

Where it goes wrong

The material cards switch the model to nonlinear: plastics.f line 73 sets iperturb(1)=3, and so do creeps.f, mohrcoulombs.f, deformationplasticitys.f and usermaterials.f. The perturbation-type cards switch it back for the rest of the analysis:

      if(iperturb(1).gt.1) iperturb(1)=0        ! frequencys.f:165, buckles.f:117, complexfrequencys.f:94
      iperturb(1)=0                             ! noanalysiss.f:45

CalculiX.c (lines 1249-1264) sends a *STATIC or *NO ANALYSIS step with iperturb[0]<2 to linstatic(). *BUCKLE goes to arpackbu(). After the frequency step, *MODAL DYNAMIC, *STEADY STATE DYNAMICS and *COMPLEX FREQUENCY go to dyna(), steadystate() and complexfreq(). All of these call results(), which still evaluates the plastic, creep or user material through mechmodel → incplas_lin / mohrcoulomb / umat_abaqusnl_total / umat_main. Those routines read the state at the start of the increment from xstateini, and user materials also read vini, stiini and emeini in resultsmech.f (lines 793, 823, 929).

arpack.c allocates the field before its results() calls (lines 367-375):

  /* field for initial values of state variables (needed if
     previous static step was viscoplastic and for contact */

  if((*nstate_!=0)&&((*mortar==0)||(ncont==0))){
    NNEW(xstateini,double,*nstate_*mi[0]*(ne0+*nslavs));

linstatic.c has the same lines (301-308), but only inside if(*mortar>-2){ (line 176), i.e. only in a model with contact. Without contact xstateini stays NULL (line 98). Its first results() call (line 351) also passes vini (never allocated) and stiini / emeini (allocated at lines 574-575 only for energy output). arpackbu.c allocates the user-material fields, with the comment “following fields are needed if *ener==1 or kode<-100” (lines 150-156), but not xstateini. dyna.c, steadystate.c and complexfreq.c have no NNEW(xstateini, ...) at all. Their results() calls run only for stress, strain, RF or contact output in dyna.c (line 1785) and steadystate.c, but every time in complexfreq.c (line 1462) and arpackbu.c (line 161). That is why the modal dynamic and steady state dynamics steps need such output to crash.

Fix

Allocate xstateini as a copy of xstate whenever *nstate_!=0 in linstatic.c, arpackbu.c, dyna.c, steadystate.c and complexfreq.c, before their first results() call, as arpack.c lines 370-375 do, and free it at the end. In linstatic.c that means moving the existing block (lines 301-308) out of if(*mortar>-2){. In addition, allocate vini, stiini and emeini unconditionally where they are now missing or tied to *nener==1 (linstatic.c, dyna.c, steadystate.c, complexfreq.c), as arpackbu.c does at lines 150-156.

This should remove the crashes (not built or tested here). One thing would stay the same: after a *FREQUENCY, *BUCKLE or *NO ANALYSIS step, a later *STATIC step of such a model is still solved by linstatic(), in one linear solve, because no step card sets iperturb(1) back.

Workaround: put NLGEOM on the *STEP card of a *STATIC step that follows a perturbation step. This sends the step back to nonlingeo(), and *FREQUENCY, then *STEP, NLGEOM *STATIC runs. In *MODAL DYNAMIC and *STEADY STATE DYNAMICS steps, request displacements only. There is no workaround for *BUCKLE, *COMPLEX FREQUENCY or *NO ANALYSIS with these materials.

Confirmed using official build of ccx 2.23 on Windows, needs a GitHub ticket.

plastic_buckle:

 STEP            1

 Buckling analysis was selected

 Decascading the MPC's

 Determining the structure of the matrix:
 Using up to 12 cpu(s) for setting up the structure of the matrix.
 number of equations
 12
 number of nonzero lower triangular matrix elements
 66

 Using up to 1 cpu(s) for the stress calculation.
1 Like

posted: Plastic, creep or user material: segfault in *NO ANALYSIS, *BUCKLE, *COMPLEX FREQUENCY, a linear *STATIC after *FREQUENCY, and modal steps with S/RF output · Issue #285 · Dhondtguido/CalculiX · GitHub

1 Like