Summary
Section 7.94 (*NO ANALYSIS) of the 2.23 manual says the procedure is “used for input deck and geometry checking only. No calculation is performed.” After a step that was solved, however, a *NO ANALYSIS step tries to write the step’s result requests to the .frd file from arrays it never filled:
- With
*EL FILES, E or ENER (the step’s own request, or one carried over from the earlier step), ccx crashes with a segmentation fault (exit status 139, no message). - With
*NODE FILEU or RF, ccx finishes with exit status 0. The .frd file then has a DISP (and FORC) block for the*NO ANALYSISstep, read from freed memory: all zeros in some runs, nonsense values in others.
The cause: linstatic.c calls frd() for the *NO ANALYSIS step with stn = NULL and with v and fn already freed.
The same requests in a *NO ANALYSIS step that is the first step of the deck run cleanly: only the mesh is written. A bare *EL FILE card (no variables) in step 2 also avoids the crash, and so does *EL PRINT S in step 1 instead of *EL FILE.
This is a different crash from the one in a *NO ANALYSIS step of a model with a plastic material (reported separately: there, xstateini is never allocated).
Low priority: the damage is limited to the end of the job. linstatic.c line 931 ends the whole job at a *NO ANALYSIS step in any case (stopwithout201, exit 0; a *STATIC step 3 after it is never run), and the earlier steps’ results are already in the .frd file. What goes wrong is the exit status (139 instead of 0) and, with U or RF requested, a step-2 block in the .frd file that a post-processor reads as results.
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: the nmethod 0 branch of linstatic.c is unchanged on master (9ba5d76).
Minimal input
na_elfile.inp: a cube loaded in step 1 with *EL FILE S, then a *NO ANALYSIS step.
*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
200000., 0.3
*SOLID SECTION, ELSET=EALL, MATERIAL=STEEL
*BOUNDARY
Z0, 1, 3
*STEP
*STATIC
*CLOAD
TOP, 3, 100.
*EL FILE
S
*END STEP
*STEP
*NO ANALYSIS
*END STEP
na_nodefile.inp is the same deck with *NODE FILE / U in place of *EL FILE / S in step 1.
How to run
ccx na_elfile and ccx na_nodefile
Expected
Step 2 prints “No analysis was selected” and the job ends with exit status 0. The .frd file holds step 1’s results and nothing for step 2, as with a bare *EL FILE card in step 2. The same deck with only the *NO ANALYSIS step (step 1 removed) also ends this way.
Actual
ccx na_elfile: step 2 prints
STEP 2
*WARNING: no analysis option was chosen
No analysis was selected
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.
Using up to 1 cpu(s) for the symmetric stiffness/mass contributions.
and the process is then killed by SIGSEGV (exit status 139). The backtrace is frdselect ← frd ← linstatic, reading address 0x0. Step 1’s results are in the .frd. E or ENER instead of S, and *EL FILE / S given in step 2 itself instead of step 1, crash the same way. The crash also happens when step 1 is *STEP, NLGEOM.
ccx na_nodefile: exit status 0. The .frd file has a second DISP block, for step 2, after step 1’s block. Step 1 gives node 7 the displacement (-3.90000E-04, -3.90000E-04, 1.82000E-03). The step 2 block holds all zeros in 8 of 20 runs. In the other 12 runs it holds values like these (nodes 1 to 4):
-1 1-1.60256E+04-2.13675E+04 3.20513E+03
-1 2-1.70940E+04-1.60256E+04-1.60256E+03
-1 3-3.20513E+03-8.01282E+03-1.60256E+04
-1 4 1.06838E+04-8.01282E+03-1.60256E+04
With *NODE FILE / U, RF in step 1, step 2 also gets a FORC block; in 8 of 10 runs it held nonzero values of the same kind.
Where it goes wrong
noanalysiss.f sets nmethod=0 (line 44), so CalculiX.c calls linstatic(). Its branch for nmethod 0 (the else at linstatic.c line 895) is commented “error occurred in mafill: storing the geometry in frd format”. In that branch it calls
++*kode;
...
frd(co,nk,kon,ipkon,lakon,ne,v,stn,inum,nmethod,
kode,filab,een,t1,fn,&ptime,epn,ielmat,matname,enern,xstaten,
with the step’s output requests (filab), and then ends the job (line 931: if(nmethodold==0){FORTRAN(stopwithout201,());}else{FORTRAN(stop,());}). stn, een and enern are still NULL there: they are only allocated in the other branches. v and fn were freed after the first results() call (line 372: SFREE(v);SFREE(fn);SFREE(stx);SFREE(inum);). In the first step, kode is 1, and frd.c writes the mesh and returns before any field:
if(*nmethod==0){fclose(f1);return;} /* frd.c line 831, inside if((*kode==1)&&...) of line 143 */
After a solved step, kode is larger than 1, so frd() goes on to the requested fields. It dereferences stn for S, een for E and enern for ENER, and it writes the freed v and fn as DISP and FORC.
Fix
In the nmethod 0 branch of linstatic.c, call frd() only when *kode is 1 after the increment. That is the case in which frd() writes just the mesh. After a solved step the mesh is already in the .frd file. Alternatively, pass empty output requests to this call. The same call serves the negative-Jacobian error path (“error occurred in mafill”), so the fix keeps the geometry output there for a first step.
Workaround: end the carried output with bare *EL FILE and *NODE FILE cards (no data line) in the *NO ANALYSIS step.