Material without *DENSITY, *SPECIFIC HEAT or *CONDUCTIVITY gets only a warning; its elements take the previous element's value, so results depend on numbering

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=TEMPERATURE is enough). In a *DYNAMIC step, a cube without *DENSITY moves as if it had the density of the cube numbered before it. Without temperatures it gets 0.
  • Specific heat, in a transient *HEAT TRANSFER or *COUPLED TEMPERATURE-DISPLACEMENT step.
  • 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 *CONDUCTIVITY is sent to the user-material routine umatht, 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:

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 and 1, 11, 12, 13, ... under EL / EB).
  • *DENSITY, *CONDUCTIVITY or *SPECIFIC HEAT lines added to, or removed from, material LIGHT / B as named.
  • “steady state”: *HEAT TRANSFER, DIRECT replaced 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, *SPRING and *DASHPOT create. 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.d0 instead of continue in materialdata_me.f and materialdata_rho.f (as c4ac748 did in materialdata_th.f), and sph=0.d0 in materialdata_th.f.
  • thermmodel.f: send only user materials (kode.le.-100) to umatht. For kode=0 set cond and qflux to 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).

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

stale_density.inp:

                        S T E P       1


                                INCREMENT     1


 displacements (vx,vy,vz) for set LTOP and time  0.1000000E+00

        15  0.000000E+00  0.000000E+00  4.000000E-04
        16 -3.636872E-20  0.000000E+00  4.000000E-04
        17 -1.936283E-20  2.675125E-20  4.000000E-04
        18  0.000000E+00  9.728661E-21  4.000000E-04

                                INCREMENT     2


 displacements (vx,vy,vz) for set LTOP and time  0.2000000E+00

        15  0.000000E+00  0.000000E+00  8.000000E-04
        16  1.501569E-20  0.000000E+00  8.000000E-04
        17  3.261417E-20 -9.734283E-21  8.000000E-04
        18  0.000000E+00  2.071399E-20  8.000000E-04

                                INCREMENT     3


 displacements (vx,vy,vz) for set LTOP and time  0.3000000E+00

        15  0.000000E+00  0.000000E+00  1.200000E-03
        16  7.889654E-20  0.000000E+00  1.200000E-03
        17  7.038384E-20  9.160704E-20  1.200000E-03
        18  0.000000E+00  8.678140E-20  1.200000E-03

                                INCREMENT     4


 displacements (vx,vy,vz) for set LTOP and time  0.4000000E+00

        15  0.000000E+00  0.000000E+00  1.600000E-03
        16  7.589928E-20  0.000000E+00  1.600000E-03
        17 -3.995392E-20 -2.377161E-20  1.600000E-03
        18  0.000000E+00  6.191339E-20  1.600000E-03

                                INCREMENT     5


 displacements (vx,vy,vz) for set LTOP and time  0.5000000E+00

        15  0.000000E+00  0.000000E+00  2.000000E-03
        16  1.054120E-19  0.000000E+00  2.000000E-03
        17  4.786163E-20 -1.761515E-20  2.000000E-03
        18  0.000000E+00  3.605178E-20  2.000000E-03

                                INCREMENT     6


 displacements (vx,vy,vz) for set LTOP and time  0.6000000E+00

        15  0.000000E+00  0.000000E+00  2.400000E-03
        16  1.139006E-20  0.000000E+00  2.400000E-03
        17 -2.849237E-20 -1.133330E-19  2.400000E-03
        18  0.000000E+00 -3.578021E-21  2.400000E-03

                                INCREMENT     7


 displacements (vx,vy,vz) for set LTOP and time  0.7000000E+00

        15  0.000000E+00  0.000000E+00  2.800000E-03
        16 -7.794509E-20  0.000000E+00  2.800000E-03
        17 -9.176272E-20 -2.342157E-20  2.800000E-03
        18  0.000000E+00 -5.651973E-20  2.800000E-03

                                INCREMENT     8


 displacements (vx,vy,vz) for set LTOP and time  0.8000000E+00

        15  0.000000E+00  0.000000E+00  3.200000E-03
        16 -1.536333E-19  0.000000E+00  3.200000E-03
        17 -8.373796E-20 -2.711592E-19  3.200000E-03
        18  0.000000E+00 -3.118120E-19  3.200000E-03

                                INCREMENT     9


 displacements (vx,vy,vz) for set LTOP and time  0.9000000E+00

        15  0.000000E+00  0.000000E+00  3.600000E-03
        16  2.021159E-19  0.000000E+00  3.600000E-03
        17 -4.451225E-20  3.054310E-20  3.600000E-03
        18  0.000000E+00  7.792431E-20  3.600000E-03

                                INCREMENT    10


 displacements (vx,vy,vz) for set LTOP and time  0.1000000E+01

        15  0.000000E+00  0.000000E+00  4.000000E-03
        16  1.168342E-19  0.000000E+00  4.000000E-03
        17 -5.943986E-20 -1.231140E-19  4.000000E-03
        18  0.000000E+00  1.057710E-19  4.000000E-03

For stale_thermal with no changes, I get zero temperatures:

                        S T E P       1


                                INCREMENT     1


 temperatures for set N17 and time  0.1000000E+00

        17  0.000000E+00

                                INCREMENT     2


 temperatures for set N17 and time  0.2000000E+00

        17  0.000000E+00

                                INCREMENT     3


 temperatures for set N17 and time  0.3000000E+00

        17  0.000000E+00

                                INCREMENT     4


 temperatures for set N17 and time  0.4000000E+00

        17  0.000000E+00

                                INCREMENT     5


 temperatures for set N17 and time  0.5000000E+00

        17  0.000000E+00

                                INCREMENT     6


 temperatures for set N17 and time  0.6000000E+00

        17  0.000000E+00

                                INCREMENT     7


 temperatures for set N17 and time  0.7000000E+00

        17  0.000000E+00

                                INCREMENT     8


 temperatures for set N17 and time  0.8000000E+00

        17  0.000000E+00

                                INCREMENT     9


 temperatures for set N17 and time  0.9000000E+00

        17  0.000000E+00

                                INCREMENT    10


 temperatures for set N17 and time  0.1000000E+01

        17  0.000000E+00