# Two \*KINEMATIC couplings on one REF NODE: the surfaces turn independently, and a moment on the reference node reaches only one, chosen by card order (exit 0)

**URL:** <https://calculix.discourse.group/t/two-kinematic-couplings-on-one-ref-node-the-surfaces-turn-independently-and-a-moment-on-the-reference-node-reaches-only-one-chosen-by-card-order-exit-0/4231>\
**Category:** Analysis issues\
**Created:** [October 22, 2026, 6:50pm UTC](https://calculix.discourse.group/t/two-kinematic-couplings-on-one-ref-node-the-surfaces-turn-independently-and-a-moment-on-the-reference-node-reaches-only-one-chosen-by-card-order-exit-0/4231 "2026-10-22T18:50:57Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sandervdb](https://avatars.discourse-cdn.com/v4/letter/s/49beb7/32.png) [@Sandervdb](https://calculix.discourse.group/u/Sandervdb)\
**Post date:** [October 22, 2026, 6:50pm UTC](https://calculix.discourse.group/t/two-kinematic-couplings-on-one-ref-node-the-surfaces-turn-independently-and-a-moment-on-the-reference-node-reaches-only-one-chosen-by-card-order-exit-0/4231/1 "2026-10-22T18:50:57Z")

</div>

## Summary

Section 7.27 (\*COUPLING) of the 2.23 manual: “With REF NODE a reference node is chosen, the degrees of freedom of which are used to define the constraint. In the reference node six degrees of freedom are available: 1 to 3 for translations […] and 4 to 6 for rotations”. Section 7.80 (\*KINEMATIC): the displacement of a coupling node “corresponds to the rigid body motion of this node about a reference node”, and a moment (DOFs 4 to 6) can be applied to the reference node by `*CLOAD`. Neither section rules out several `*KINEMATIC` couplings on the same reference node. Section 7.27 does say that “it is not recommended to use the reference node in any other construct”, but in its paragraph on `*DISTRIBUTING` couplings. So the nodes of all couplings on one reference node should follow that node’s translations and rotations, i.e. move as one rigid body; if this is not meant to be supported, I would expect a message.

ccx gives each `*KINEMATIC` card its own internal rotation node. With two cards on one reference node the two surfaces share the reference node’s translations but not its rotations: they behave like two rigid bodies joined by a ball joint at the reference node. A moment on the reference node acts on only one of the two surfaces, and swapping the two cards in the deck swaps which one, so the sign of the response flips. The same goes for a `*BOUNDARY` on DOFs 4 to 6: with the reference node clamped in all six DOFs, one of the two surfaces can still turn about it, again chosen by card order. Exit 0, no message.

Test: two separate cantilevers (two C3D8 each), their free end faces coupled to one reference node between them. With one `*COUPLING` over both end faces, or with a `*RIGID BODY` over the same nodes, or with two `*RIGID BODY` cards sharing the reference and rotation node, a force in z at the reference node moves it 0.03444 and a moment about x does not move it in z. With one `*COUPLING` per end face: 0.05004 (+45 %) and ∓0.0156.

## 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 22 Oct 2026). Not fixed: the `*KINEMATIC` branch of `couplings.f` is unchanged on master (9ba5d76); master changed only the REF NODE parsing and the `*DISTRIBUTING` part.

## Minimal input

`two_kin.inp`: bar A (elements 1, 2; y from 0 to 1) and bar B (elements 11, 12; y from 2 to 3), both clamped at x = 0. Their end faces at x = 2 are coupled to node 100 at (3, 1.5, 0.5) by one `*KINEMATIC` coupling each. A force of 1 in z acts on node 100.

```auto
** two separate cantilevers A (elements 1, 2) and B (elements 11, 12), both
** clamped at x = 0; their end faces at x = 2 are coupled to reference node
** 100 by one *KINEMATIC coupling each; load on node 100
*NODE, NSET=NALL
1, 0., 0., 0.
2, 1., 0., 0.
3, 2., 0., 0.
4, 0., 1., 0.
5, 1., 1., 0.
6, 2., 1., 0.
7, 0., 0., 1.
8, 1., 0., 1.
9, 2., 0., 1.
10, 0., 1., 1.
11, 1., 1., 1.
12, 2., 1., 1.
21, 0., 2., 0.
22, 1., 2., 0.
23, 2., 2., 0.
24, 0., 3., 0.
25, 1., 3., 0.
26, 2., 3., 0.
27, 0., 2., 1.
28, 1., 2., 1.
29, 2., 2., 1.
30, 0., 3., 1.
31, 1., 3., 1.
32, 2., 3., 1.
100, 3., 1.5, 0.5
*ELEMENT, TYPE=C3D8, ELSET=EALL
1, 1, 2, 5, 4, 7, 8, 11, 10
2, 2, 3, 6, 5, 8, 9, 12, 11
11, 21, 22, 25, 24, 27, 28, 31, 30
12, 22, 23, 26, 25, 28, 29, 32, 31
*NSET, NSET=CLAMP
1, 4, 7, 10, 21, 24, 27, 30
*NSET, NSET=REF
100
*MATERIAL, NAME=M
*ELASTIC
1000., 0.3
*SOLID SECTION, ELSET=EALL, MATERIAL=M
*SURFACE, NAME=SA
2, S4
*SURFACE, NAME=SB
12, S4
*COUPLING, REF NODE=100, SURFACE=SA, CONSTRAINT NAME=CA
*KINEMATIC
1, 3
*COUPLING, REF NODE=100, SURFACE=SB, CONSTRAINT NAME=CB
*KINEMATIC
1, 3
*BOUNDARY
CLAMP, 1, 3
*STEP
*STATIC
*CLOAD
100, 3, 1.
*NODE PRINT, NSET=REF
U
*NODE PRINT, NSET=NALL
U
*END STEP

```

Variants (each changes only the lines shown):

- `two_kin_swap.inp`: the two `*COUPLING` cards (each with its `*KINEMATIC` and `1, 3` line) in the opposite order, CB first.

- `one_kin.inp`: one coupling over both end faces; the two `*SURFACE` cards and the two couplings replaced by

- `one_rb.inp`: a `*RIGID BODY` over the same eight nodes instead; node `101, 3., 1.5, 0.5` added after node 100, and the surfaces and couplings replaced by

- `two_rb.inp`: as `one_rb.inp`, but with one `*RIGID BODY` card per end face, both on REF NODE 100 and ROT NODE 101:

Loads (the `*CLOAD` line): `100, 3, 1.` (force in z, as printed), `100, 1, 1.` (force in x), `100, 4, 1.` (moment about x), `100, 6, 1.` (moment about z). In the `*RIGID BODY` decks a moment goes on the rotation node: `101, 1, 1.` for the moment about x, `101, 3, 1.` for the moment about z.

Clamped reference node: `two_kin_held.inp`, `two_kin_swap_held.inp` and `one_kin_held.inp` are `two_kin.inp`, `two_kin_swap.inp` and `one_kin.inp` with the line `100, 1, 6` added after `CLAMP, 1, 3` and the `*CLOAD` line replaced by `29, 3, 1.` (a force in z on node 29, on the coupled end face of bar B).

## How to run

```auto
ccx two_kin
ccx two_kin_swap
ccx one_kin
ccx one_rb
ccx two_rb

```

(once per load), and

```auto
ccx two_kin_held
ccx two_kin_swap_held
ccx one_kin_held

```

## Expected

All five decks describe the same structure: the end faces of both bars moving rigidly with node 100. They should give the same displacements, and by symmetry a moment about x or z should not move node 100 in z or x. In the `_held` decks node 100 is clamped, so the coupled end faces cannot move at all: node 29 should stay at 0.

## Actual

Displacement of node 100 (exit 0 in every run):

| load on node 100 | component | `one_kin`, `one_rb` | `two_kin` | `two_kin_swap` |
| --- | --- | --- | --- | --- |
| force in x | u1 | 9.100000E-04 | 1.857040E-03 | 1.857040E-03 |
| force in z | u3 | 3.444381E-02 | 5.004381E-02 | 5.004381E-02 |
| moment about x | u3 | -1.950326E-17 | -1.560000E-02 | 1.560000E-02 |
| moment about z | u1 | -5.362901E-19 | 9.470405E-04 | -9.470405E-04 |

`two_rb` gives the `one_rb` values for every load. A force in y and a moment about y give the same u at node 100 in all decks (7.580758E-03 and -1.505524E-02).

Under the force in z, `one_kin` moves the end faces without turning them about x (nodes 3, 6, 23 and 26 all 1.938857E-02 in z), while in `two_kin` they turn in opposite directions about x: node 3 1.158857E-02, node 6 2.718857E-02, node 23 2.718857E-02, node 26 1.158857E-02.

With the reference node clamped (exit 0 in all three runs), `one_kin_held` and `two_kin_held` keep nodes 23, 26, 29 and 32 at 0. In `two_kin_swap_held` the end face of bar B turns about the clamped node 100: node 29 moves (6.518225E-04, -6.754082E-04, 1.979053E-03) and node 26 (-6.518225E-04, 6.754082E-04, 3.329870E-03).

## Where it goes wrong

`src/couplings.f`, for each `*KINEMATIC` card (master lines 334-390, 2.23 lines 311-367), creates a new rotation node `irotnode_kin` (line 347) and three `ROTTRACOUPLING` MPCs between the reference node’s DOFs 4-6 and that node’s translations:

```fortran
          labmpc(nmpc)='ROTTRACOUPLING '
          idof=8*(irefnode-1)+k+3
          call nident(ikmpc,idof,nmpc-1,id)
          do l=nmpc,id+2,-1
            ikmpc(l)=ikmpc(l-1)
            ilmpc(l)=ilmpc(l-1)
          enddo
          ikmpc(id+1)=idof
          ilmpc(id+1)=nmpc

```

The coupling nodes are then tied to the reference node and to `irotnode_kin` by `rigidmpc` (lines 476-484). A second card on the same reference node gets a second rotation node, and its `ROTTRACOUPLING` MPCs are inserted into `ikmpc` with the same dependent DOFs as the first card’s, without a check (lines 370-377). Nothing ties the two rotation nodes together, so each surface has its own rotation.

The `ROTTRACOUPLING` MPCs are what `forcadd.f` (lines 48-62) and `bounadd.f` (lines 55-77) use to send a `*CLOAD` or `*BOUNDARY` on DOFs 4-6 of the reference node to the rotation node: they look the DOF up with `nident(ikmpc,idof,...)` and take the rotation node of the entry they find. With two entries for the same DOF the lookup finds one of them, so a moment reaches only one rotation node and a `*BOUNDARY` on DOFs 4-6 holds only one, and which one depends on the order of the cards.

`*RIGID BODY` does not have the problem, because the user can give both cards the same ROT NODE (`two_rb.inp`).

## Fix

Possible fix (not built or tested): in `couplings.f`, before creating a rotation node, look up `8*(irefnode-1)+4` in `ikmpc`. If it is already there with label `ROTTRACOUPLING`, take that MPC’s rotation node (`nodempc(1,nodempc(3,ipompc(ilmpc(id))))`, as `forcadd.f` does) as `irotnode_kin` and skip the new node and the three new MPCs. All couplings on one reference node then share one rotation, as two `*RIGID BODY` cards with the same ROT NODE do. If sharing is not meant to be supported, an \*ERROR when a reference node gets a second `*KINEMATIC` coupling would at least avoid the silent result.

Workaround: put all surfaces that should move together with one reference node into one `*SURFACE` and one `*COUPLING` (`one_kin.inp`), or use `*RIGID BODY` cards with a common ROT NODE.

---

<div class="post-metadata">

**Author:** ![Calc\_em](https://avatars.discourse-cdn.com/v4/letter/c/43a26b/32.png) [@Calc\_em](https://calculix.discourse.group/u/Calc_em)\
**Post date:** [October 22, 2026, 7:57pm UTC](https://calculix.discourse.group/t/two-kinematic-couplings-on-one-ref-node-the-surfaces-turn-independently-and-a-moment-on-the-reference-node-reaches-only-one-chosen-by-card-order-exit-0/4231/2 "2026-10-22T19:57:17Z")

</div>

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

two\_kin.dat:

`100 3.718670E-18 1.757190E-17 5.004381E-02`

two\_kin\_swap.dat:

`100 3.718670E-18 1.757190E-17 5.004381E-02`

one\_kin.dat:

`100 -1.423228E-18 7.538206E-18 3.444381E-02`

---

<div class="post-metadata">

**Author:** ![Sandervdb](https://avatars.discourse-cdn.com/v4/letter/s/49beb7/32.png) [@Sandervdb](https://calculix.discourse.group/u/Sandervdb)\
**Post date:** [October 22, 2026, 8:38pm UTC](https://calculix.discourse.group/t/two-kinematic-couplings-on-one-ref-node-the-surfaces-turn-independently-and-a-moment-on-the-reference-node-reaches-only-one-chosen-by-card-order-exit-0/4231/3 "2026-10-22T20:38:20Z")

</div>

posted: [Two \*KINEMATIC couplings on one REF NODE: the surfaces turn independently, and a moment on the reference node reaches only one, chosen by card order (exit 0) · Issue #281 · Dhondtguido/CalculiX · GitHub](https://github.com/Dhondtguido/CalculiX/issues/281)
