Summary
The 2.23 manual says which material data a step needs. Section 7.36 (*DENSITY) of the 2.23 manual: “The mass density is required for a frequency analysis (*FREQUENCY), for a dynamic analysis (*DYNAMIC or *HEAT TRANSFER) and for a static analysis with gravity loads (GRAV) or centrifugal loads (CENTRIF).” Section 7.121 (*SPECIFIC HEAT): “The specific heat is required for a transient heat transfer analysis (*HEAT TRANSFER or *COUPLED TEMPERATURE-DISPLACEMENT).”
A material without such data is therefore incomplete input. ccx 2.23 does not stop on it. calinput.f prints a warning for each such material (“no density was assigned to material LIGHT …”) and stops with an *ERROR only when no material at all has the card (lines 1663-1670 and 1691-1698). For a missing *CONDUCTIVITY it only warns.
The run then goes on, and the elements of such a material get the value of the element assembled just before them:
- Density, as soon as temperatures are defined (an
*INITIAL CONDITIONS, TYPE=TEMPERATUREis enough). In a*DYNAMICstep, a cube without*DENSITYmoves as if it had the density of the cube numbered before it. Without temperatures it gets 0. - Specific heat, in a transient
*HEAT TRANSFERor*COUPLED TEMPERATURE-DISPLACEMENTstep. - Conductivity, in a transient heat step. Section 7.17 (*CONDUCTIVITY) does not call it required, but the code has no defined value for it: a material without
*CONDUCTIVITYis sent to the user-material routineumatht, which sets nothing (see “Where it goes wrong”). - Density in the heat capacity: the same in 2.23. Master fixed this one in c4ac748 (see below).
Renumbering the elements changes the results, with exit 0 and only the warnings above. In these runs a material numbered first got zero.
In a steady-state heat step, a material without *CONDUCTIVITY stops the run instead. ccx exits with status 255, and stdout shows only the warning. The only error message is “matrix found to be singular” in spooles.out.
So missing required data gives another element’s value. It should give an *ERROR that names the material, as ccx already does when no material has the card.
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). Partly fixed: master’s c4ac748 (28 Apr 2026, “made a change for zero density in materialdata_th.f”) sets the density of the heat capacity to 0 for a material without *DENSITY. Not fixed: the density branch of materialdata_me.f, the specific heat in materialdata_th.f and the conductivity path in thermmodel.f are unchanged on master (9ba5d76).
Related:
- Thermal contact calinput warnings and Uncoupled thermal transient analysis users ask about the same
calinputwarnings (“no specific heat”, “no conductivity constants”) for the pseudo-materials that*SURFACE INTERACTIONcreates. They show that these checks also run over materials that are not meant to have such data, which a fix has to respect (see “Fix”). - Issues · Dhondtguido/CalculiX · GitHub the same silent SPOOLES stop (exit 255, message only in
spooles.out), with a different cause (element deletion).
Minimal input
stale_density.inp: two separate unit cubes. Element 1 (material HEAVY) has density 1. Element 2 (material LIGHT) has no *DENSITY and is pulled at its top by a ramped force in a *DYNAMIC step.
** Two separate unit cubes. Cube H (element 1, material HEAVY) has density 1.
** Cube L (element 2, material LIGHT) has no *DENSITY. Its bottom is held and
** its top is pulled by a force ramped from 0 to 4 in a *DYNAMIC step.
** A massless cube L follows the load: U3 = 4e-4 per increment at node 17.
*NODE, NSET=NALL
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.
11, 3., 0., 0.
12, 4., 0., 0.
13, 4., 1., 0.
14, 3., 1., 0.
15, 3., 0., 1.
16, 4., 0., 1.
17, 4., 1., 1.
18, 3., 1., 1.
*ELEMENT, TYPE=C3D8, ELSET=EH
1, 1, 2, 3, 4, 5, 6, 7, 8
*ELEMENT, TYPE=C3D8, ELSET=EL
2, 11, 12, 13, 14, 15, 16, 17, 18
*NSET, NSET=HBOT
1, 2, 3, 4
*NSET, NSET=LBOT
11, 12, 13, 14
*NSET, NSET=LTOP
15, 16, 17, 18
*MATERIAL, NAME=HEAVY
*ELASTIC
1000., 0.
*DENSITY
1.
*MATERIAL, NAME=LIGHT
*ELASTIC
1000., 0.
*SOLID SECTION, ELSET=EH, MATERIAL=HEAVY
*SOLID SECTION, ELSET=EL, MATERIAL=LIGHT
*INITIAL CONDITIONS, TYPE=TEMPERATURE
NALL, 20.
*AMPLITUDE, NAME=RAMP
0., 0., 1., 1.
*STEP, INC=100
*DYNAMIC, DIRECT
0.1, 1.
*BOUNDARY
HBOT, 1, 3
LBOT, 1, 3
15, 1, 2
16, 2, 2
18, 1, 1
*CLOAD, AMPLITUDE=RAMP
LTOP, 3, 1.
*NODE PRINT, NSET=LTOP
U
*END STEP
stale_thermal.inp: two separate unit cubes, both heated to 100 at their bottom face in a transient *HEAT TRANSFER step. Element 1 (material A) has conductivity 5. Element 2 (material B) has density and specific heat but no *CONDUCTIVITY. Node 17 is the top corner of cube B.
** Two separate unit cubes, both heated to 100 at their bottom face (start 0).
** Cube A (element 1): conductivity 5, density 1, specific heat 1.
** Cube B (element 2): density 1, specific heat 1, no *CONDUCTIVITY.
** If B does not conduct, its top node 17 stays at 0.
*NODE, NSET=NALL
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.
11, 3., 0., 0.
12, 4., 0., 0.
13, 4., 1., 0.
14, 3., 1., 0.
15, 3., 0., 1.
16, 4., 0., 1.
17, 4., 1., 1.
18, 3., 1., 1.
*ELEMENT, TYPE=DC3D8, ELSET=EA
1, 1, 2, 3, 4, 5, 6, 7, 8
*ELEMENT, TYPE=DC3D8, ELSET=EB
2, 11, 12, 13, 14, 15, 16, 17, 18
*NSET, NSET=BOT
1, 2, 3, 4, 11, 12, 13, 14
*NSET, NSET=N17
17
*MATERIAL, NAME=A
*CONDUCTIVITY
5.
*DENSITY
1.
*SPECIFIC HEAT
1.
*MATERIAL, NAME=B
*DENSITY
1.
*SPECIFIC HEAT
1.
*SOLID SECTION, ELSET=EA, MATERIAL=A
*SOLID SECTION, ELSET=EB, MATERIAL=B
*INITIAL CONDITIONS, TYPE=TEMPERATURE
NALL, 0.
*STEP, INC=100
*HEAT TRANSFER, DIRECT
0.1, 1.
*BOUNDARY
BOT, 11, 11, 100.
*NODE PRINT, NSET=N17
NT
*END STEP
How to run
ccx stale_density
ccx stale_thermal
The variants in the tables change one or two lines:
- “swapped”: element numbers 1 and 2 exchanged (
2, 1, 2, 3, ...under EH / EA and1, 11, 12, 13, ...under EL / EB). *DENSITY,*CONDUCTIVITYor*SPECIFIC HEATlines added to, or removed from, material LIGHT / B as named.- “steady state”:
*HEAT TRANSFER, DIRECTreplaced by*HEAT TRANSFER, STEADY STATE.
Expected
An *ERROR that names the material, since the manual requires the density for *DYNAMIC and the specific heat for transient heat transfer. As long as ccx accepts the input with a warning instead, the element numbering must not change the results, and the material should behave as with the value 0. That is what ccx itself gives when the element is numbered first, and, for the density, when no temperatures are defined:
stale_density.inp: cube L is massless, so its top follows the load quasi-statically. U3 at node 17 = 4e-4 per increment (4.000000E-04, …, 4.000000E-03). ccx gives exactly this with LIGHT given*DENSITY 0., with the elements swapped, or without the*INITIAL CONDITIONS.stale_thermal.inp: cube B does not conduct, so node 17 stays at 0. ccx gives this with B given*CONDUCTIVITY 0., or with the elements swapped.- Steady state: the temperature of a part that does not conduct is undefined, so the run cannot finish. The expected stop is an *ERROR on stdout that names the material, as ccx gives for other input problems, not exit status 255 with the reason only in
spooles.out.
Actual
stale_density.inp, U3 of node 17 at t = 0.1, 0.2, …, 1.0 (exit 0 in every run):
| run | U3 (node 17) |
|---|---|
as written (LIGHT has no *DENSITY) |
3.548294E-04, 8.644140E-04, 1.149863E-03, 1.613733E-03, 2.024260E-03, 2.354638E-03, 2.841757E-03, 3.181422E-03, 3.589661E-03, 4.030305E-03 |
LIGHT given *DENSITY 1. |
the same, digit for digit |
| HEAVY’s density changed to 5. | 2.444223E-04, 8.560068E-04, 1.327224E-03, … (LIGHT follows) |
| swapped | 4.000000E-04, 8.000000E-04, …, 4.000000E-03 |
LIGHT given *DENSITY 0. |
4.000000E-04, 8.000000E-04, …, 4.000000E-03 |
without *INITIAL CONDITIONS |
4.000000E-04, 8.000000E-04, …, 4.000000E-03 |
stale_thermal.inp, temperature of node 17 at t = 0.1, 0.2, 0.3, 0.4, …, 1.0:
| run | NT (node 17) |
|---|---|
as written (B has no *CONDUCTIVITY) |
60.0, 84.0, 93.6, 97.44, …, 99.98951 |
B given *CONDUCTIVITY 5. (A’s value) |
the same, digit for digit |
| swapped | 0 at every time |
B given *CONDUCTIVITY 0. |
0 at every time |
B: *CONDUCTIVITY 5. added, *SPECIFIC HEAT removed |
60.0, 84.0, 93.6, … (as with B’s specific heat 1 = A’s) |
| the same, A’s specific heat changed to 3. | 33.33333, 55.55556, 70.37037, … (= B given *SPECIFIC HEAT 3.) |
| the same, swapped | 100 at every time (= B given *SPECIFIC HEAT 0.) |
B: *CONDUCTIVITY 5. added, *DENSITY removed |
60.0, 84.0, 93.6, … ; swapped: 100 at every time |
| steady state (either numbering) | exit status 255 |
Each run without the card prints only the warning, e.g.
*WARNING in calinput: no conductivity
constants were assigned to material B
in a thermo(mechanical) calculation
In the steady-state run stdout ends with “Newton-Raphson iterative procedure is active”, and spooles.out contains “matrix found to be singular”. As a *COUPLED TEMPERATURE-DISPLACEMENT, DIRECT step (stale_thermal.inp with C3D8 instead of DC3D8, *ELASTIC 1000., 0. added to both materials, and the base, set BOT, held) every run in the table gives the same temperatures and exit codes.
Where it goes wrong
Density, src/materialdata_me.f (master lines 82-87, the same in 2.23):
if(ithermal(1).eq.0) then
rho=rhcon(1,1,imat)
else
call ident2(rhcon(0,1,imat),t1l,nrhcon(imat),two,id)
if(nrhcon(imat).eq.0) then
continue
Without temperatures, rhcon(1,1,imat) is 0 for a material without *DENSITY. With temperatures, rho is not set, and the element routine uses whatever rho still holds. materialdata_rho.f has the same branch.
Specific heat, src/materialdata_th.f (master lines 65-67): if(nshcon(imat).eq.0) then / continue, so sph is not set either. In 2.23 the density in the same routine had the same continue. Master’s c4ac748 replaced it by rho=0.d0 (lines 47-49) but left the specific heat as it was.
Conductivity: resultstherm.f (line 519) passes kode=ncocon(1,imat) to thermmodel.f, and kode is 0 for a material without *CONDUCTIVITY. thermmodel.f handles kode=1 (line 43) and kode=3 or 6 (line 58). Every other value goes to the user-material branch (line 128), which calls umatht. That branch is meant for *USER MATERIAL, which usermaterials.f (line 146) marks with ncocon(1,nmat)=-100-nconstants; kode=0 reaches it only because the test is a bare else. The default umatht.f sets nothing (line 115: “insert here your code”). thermmodel.f then copies cond(1..6) from dfdg (lines 154-159), which nothing has set, and stores it as the element’s conductivity (lines 163-167). What a material without *CONDUCTIVITY conducts is therefore not defined by the code. In the transient runs above it is the previous element’s conductivity. In the steady-state runs the system is singular. How the previous element’s value gets there was not traced further.
The steady-state stop comes from spooles.c (lines 225-226), which writes “matrix found to be singular” to spooles.out and calls exit(-1) without a message on stdout.
Fix
Not built or tested:
- In
calinput.f, stop with an *ERROR that names the material when a material used by the elements lacks data the step requires (density, specific heat), and when a heat transfer step has a material without conductivity. The check must skip the pseudo-materials that*SURFACE INTERACTION,*SPRINGand*DASHPOTcreate. The density check already skips SPRING and DASHPOT by name (lines 1649-1650); the specific heat and conductivity checks skip nothing, which is why the two forum topics linked above (Thermal contact calinput warnings and Uncoupled thermal transient analysis) see these warnings for surface interactions. Checking only the materials of the continuum, shell and beam elements would cover both. - Wherever a missing value is still accepted, define it:
rho=0.d0instead ofcontinueinmaterialdata_me.fandmaterialdata_rho.f(as c4ac748 did inmaterialdata_th.f), andsph=0.d0inmaterialdata_th.f. thermmodel.f: send only user materials (kode.le.-100) toumatht. Forkode=0setcondandqfluxto 0.- Report the SPOOLES failure of the steady-state run on stdout.
Workaround: give every material the cards explicitly (*DENSITY 0., *SPECIFIC HEAT 0., and a tiny *CONDUCTIVITY such as 1e-30 where a steady-state step needs one).