Here are more cases of the same missing *ORIENTATION input check as in the first post, this time with plain data lines instead of a distribution name. The input is invalid: section 7.103 (*ORIENTATION) of the 2.23 manual defines a rectangular system by “a point a on the local X’ axis and a point b belonging to the X’-Y’ plane but not on the X’ axis”, which rules out a at the origin and b on the X’ axis.
So I am not asking ccx to accept such a line. I am asking for a clear *ERROR that names the orientation, instead of NaN output (isotropic material, exit 0) or an exit with no message (orthotropic material, exit 255).
Users do write such lines. The 2021 topic TYPE ORTHO not known hit the same input: post 1 has a = (0, 0, 0) (0.,0.,0.,1.,0.,0. and 0.,0.,0.,0.,1.,0.), and Calc_em traced that run’s failure to the orientation by reading the input (post 5). Post 14 there (2023) has 1.,1.,0.,0.,0.,0., i.e. b = (0, 0, 0), which lies on the X’ axis through a; that case was not resolved in the topic.
Checked on ccx 2.23 (macOS arm64); orientations.f, transforms.f, transformatrix.f and umat_def_plas.f are unchanged on current master (537aa81, 2 Nov 2026), and the *DEFORMATION PLASTICITY and *TRANSFORM cases at the end were also run on that master.
The cases
The first post already showed the orthotropic stop for 0., 0., 0., 0., 0., 0.. Three more plain data lines do the same:
- only point a (
1., 0., 0.): the missing b is read as (0, 0, 0), which lies on the X’ axis;
- b on the axis (
1., 0., 0., 2., 0., 0.);
- a at the origin (
0., 0., 0., 1., 0., 0.).
transformatrix.f then divides by a zero length, and the local axes are NaN:
- Isotropic material: the run finishes with exit 0 and correct displacements. But the element stresses, which ccx prints in the local system, have NaN in five of their six components (all six for a = 0). There is no warning.
- Orthotropic material (
TYPE=ENGINEERING CONSTANTS): exit status 255. stdout shows nothing after “Static analysis was selected”, and spooles.out contains “matrix found to be singular”, as in the first post.
Deck
ori_degenerate.inp:
** Unit cube, uniaxial stress 1 in x. The *ORIENTATION line gives point a
** only: point b is (0,0,0), which lies on the local x axis.
*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=XMAX
2, 3, 6, 7
*MATERIAL, NAME=MAT
*ELASTIC
1000., 0.
*ORIENTATION, NAME=OR
1., 0., 0.
*SOLID SECTION, ELSET=EALL, MATERIAL=MAT, ORIENTATION=OR
*BOUNDARY
1, 1, 3
4, 1, 1
4, 3, 3
5, 1, 2
8, 1, 1
*STEP
*STATIC
*CLOAD
XMAX, 1, 0.25
*NODE PRINT, NSET=XMAX
U
*EL PRINT, ELSET=EALL
S
*END STEP
Run it with ccx ori_degenerate.
For the other two cases replace the line under *ORIENTATION by 1., 0., 0., 2., 0., 0. or 0., 0., 0., 1., 0., 0.; for the reference, by 1., 0., 0., 0., 1., 0.. For the orthotropic case replace the *ELASTIC lines by
*ELASTIC, TYPE=ENGINEERING CONSTANTS
1000., 100., 100., 0., 0., 0., 50., 50.
50.
Expected
An *ERROR that orientation OR is degenerate (a at the origin, or b missing or on the local X’ axis), since section 7.103 rules these points out. With the valid line 1., 0., 0., 0., 1., 0. ccx gives u_x = 1.000000E-03 at nodes 2, 3, 6, 7 and the stresses 1, 0, 0, 0, 0, 0 (to 1e-16), for both materials.
Actual
Isotropic, as written: exit 0. The displacements are right (u_x = 1.000000E-03 at node 7). The stresses:
stresses (elem, integ.pnt.,sxx,syy,szz,sxy,sxz,syz) for set EALL and time 0.1000000E+01
1 1 1.000000E+00 NaN NaN NaN NaN NaN OR
and the same for integration points 2-8. 1., 0., 0., 2., 0., 0. gives the same output. 0., 0., 0., 1., 0., 0. gives NaN in all six components, also with exit 0.
Orthotropic: exit status 255 with any of the three lines. stdout ends with “Static analysis was selected”, and spooles.out contains “matrix found to be singular”.
Where it goes wrong
src/orientations.f (master lines 88-95, quoted in the first post) reads six reals from the data line. Missing fields read as 0 without an error, and nothing checks the two points. src/transformatrix.f (lines 46-59) then normalises a, removes its component from b, and normalises the rest:
dd=dsqrt(e2(1)*e2(1)+e2(2)*e2(2)+e2(3)*e2(3))
do j=1,3
e2(j)=e2(j)/dd
enddo
When b is on the X’ axis, dd is 0 and e2 and e3 become NaN. When a is the origin, the first normalisation (lines 46-49) already divides by 0. The cylindrical branch of the same routine already treats its degenerate case (a point on the axis, lines 91-111). The rectangular branch has no such guard.
Possible fix
In orientations.f, after reading a plain orientation, stop with an *ERROR naming the orientation when |a| = 0 or when b has no component perpendicular to a (relative to |a| |b|). That is the check suggested at the end of the first post. It should not change any valid input: for a valid orientation both quantities are clearly nonzero.
*DEFORMATION PLASTICITY: a hang instead of NaN
With *DEFORMATION PLASTICITY, the same input never finishes. In ori_degenerate.inp, replace the *ELASTIC lines by
*DEFORMATION PLASTICITY
1000., 0., 10., 5., 0.5
With any of the three degenerate lines (1., 0., 0.; 1., 0., 0., 2., 0., 0.; 0., 0., 0., 1., 0., 0.), ccx 2.23 and master 537aa81 hang: the first increment never ends. The .sta file stays empty, stdout stops after “Nonlinear geometric effects are taken into account”, and the run uses full CPU until it is killed (I stopped it after 60 s). With the valid line 1., 0., 0., 0., 1., 0., or without the orientation, the run finishes at once with u_x = 1.000500E-03 at node 7.
A stack sample of the hanging 2.23 process shows every sample in umat_def_plas, called from umat_abaqusnl_total ← mechmodel ← resultsmech ← results ← nonlingeo. The NaN local axes reach the Newton loop for the Mises stress in src/umat_def_plas.f (lines 88-93, the same in 2.23 and on master):
do
c2=al*(q/s0)**(xn-1.d0)
dq=(ee*eq-(c1+c2)*q)/(c1+xn*c2)
if((dabs(dq).lt.q*1.d-4).or.(dabs(dq).lt.1.d-10)) exit
q=q+dq
enddo
The loop has no iteration limit, and with q = NaN the exit test is never true. The orientation check above would prevent this. An iteration limit with an *ERROR in that loop would also turn any other NaN strain into a message instead of a hang.
The same gap in *TRANSFORM
Section 7.135 (*TRANSFORM) of the 2.23 manual defines a rectangular system with the same two points, “a point a on the local X’ axis and a point b belonging to the X’-Y’ plane but not on the X’ axis”, and transforms.f also stores them without a check. They go through the same transformatrix.f (lines 46-49 and 56-59), so the division by zero is the same. But *TRANSFORM never passes through orientations.f, so the check has to be made in transforms.f as well, after the data line is read (line 97).
tr_a0.inp, a unit cube whose four nodes at x = 1 carry a rectangular *TRANSFORM with a at the origin:
** Unit cube (E = 1000, nu = 0); the four nodes at x = 1 carry a *TRANSFORM
** and a load of 0.25 in local direction 1.
*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=XMAX
2, 3, 6, 7
*MATERIAL, NAME=MAT
*ELASTIC
1000., 0.
*SOLID SECTION, ELSET=EALL, MATERIAL=MAT
*TRANSFORM, NSET=XMAX, TYPE=R
0., 0., 0., 1., 0., 0.
*BOUNDARY
1, 1, 3
4, 1, 1
4, 3, 3
5, 1, 2
8, 1, 1
*STEP
*STATIC
*CLOAD
XMAX, 1, 0.25
*NODE PRINT, NSET=XMAX
U
*END STEP
ccx 2.23 and master 537aa81, all with “Job finished”, exit 0 and no warning:
- this deck (a at the origin): every free displacement in the model is NaN, also at the nodes without a transform;
1., 0., 0., 2., 0., 0. (b on the X’ axis): the transformed nodes move 1.000000E-03 NaN NaN (local system);
1., 0., 0., 0., 1., 0. (valid): 1.000000E-03 -7.255989E-20 -1.402057E-19;
*TRANSFORM, NSET=XMAX, TYPE=C with 0., 0., 0., 0., 0., 0. (a = b, no axis): again every free displacement is NaN.