I am trying to model a 5-story building with 9 column axes in FLAC2D. For this, I created all structural members (columns, beams, and slabs) using the structure beam create by-line command. After completing the geometry, I attempted to connect the nodes with structure node join. However, I received the error message “recursive rigid link exist”. To solve this, I tried using the range-target option and manually created rigid connections for the nodes one by one. This seemed to work for some parts, but when I check the label > attach conditions, I still find several nodes that are shown as free or no-link. The analysis seems to run, but I’m observing unexpected stress values in the zones beneath the building, which I suspect is due to incorrect or incomplete node associations.
So my question is: For models with many nodes and connection points (like multi-story frame structures), what is the most efficient and reliable way to establish the node-to-node connections without creating recursive rigid links?
I’m not sure this will be helpful, but did you try give all the horizontal structural elements the same id and the vertical structural elements a different id? That way when you use the structure node join command only one link can be made at the intersecting nodes i.e. where vertical and horizontal elements intersect.
Hi Derrick,
Thank you for your suggestion. I actually tried grouping the beams and columns separately by assigning them different ID numbers. In this way, I was able to rigidly connect all the structural nodes. However, when I proceed with the analysis, I encounter the error “recursive rigid link”.
As a workaround, if I assign free connections to all the beams and keep the columns as rigid connections, the analysis runs without any error. But I am not sure whether this approach is correct. Do you think keeping the beams as free connections and the columns as rigid ones is an acceptable solution, or am I missing a better way to properly establish the node-to-node connections? To better illustrate my question, I have prepared a figure and attached it.
Thanks again for your time and help!
As you know, when creating links between nodes (especially with more than three nodes), the links should not form a recursive loop.
In other words, a link target should never loop back into its source node.
This situation often arises when connecting multiple nodes using the struct node join command.
There are two main solutions:
1. Define source and target nodes explicitly when creating links.
This prevents recursion from occurring in the first place. (You can find details on how to do this below)
2. Use FISH scripting.
First, create the links using struct node join. Then, identify nodes that share the same position and check their corresponding links.
To avoid recursive rigid link conditions, remember:
The number of links should always be less than the number of nodes.
For example, with three nodes at the same position, two links are correct:
node: 1 → 2 → 3
link: 1 2
This is fine.
But if you connect them in a loop:
node: 1 → 2 → 3 → 1
link: 1 2 3
This creates a recursive rigid link, which must be avoided.
With FISH, you can write a simple check:
If the number of links is equal to or greater than the number of nodes, delete the last link.
The following example FISH code is written for FLAC3D (not FLAC2D), but you can still learn the logic from it and adapt it as needed.
Best regards,
model new
model configure dynamic
model deterministic off
program thread automatic
zone create brick point 0 (0,0,0) point 1 (1,0,0) point 4 (1,1,0) point 2 (0,1,0) &
point 3 (0,0,1) point 6 (1,0,1) point 7 (1,1,1) point 5 (0,1,1) size 2, 2, 2 group 'A'
zone create brick point 0 (0,-1,0) point 1 (1,-1,0) point 4 (1,0,0) point 2 (0,0,0) &
point 3 (0,-1,1) point 6 (1,-1,1) point 7 (1,0,1) point 5 (0,0,1) size 2, 2, 2 group 'B'
zone create brick point 0 (1,-1,0) point 1 (2,-1,0) point 4 (2,0,0) point 2 (1,0,0) &
point 3 (1,-1,1) point 6 (2,-1,1) point 7 (2,0,1) point 5 (1,0,1) size 2, 2, 2 group 'C'
zone separate by-zone range-1 group 'A'
zone separate by-zone range-1 group 'C'
structure shell create by-zone-face id 10 range position-z 1 group 'B'
structure shell create by-zone-face id 20 range position-z 1 group 'A'
structure shell create by-zone-face id 30 range position-x 1 group 'B'
structure shell create by-zone-face id 40 range position-x 1 group 'A'
structure shell create by-zone-face id 50 range position-z 0 group 'B'
structure shell create by-zone-face id 60 range position-z 0 group 'A'
zone cmodel elastic
structure node join
zone property density 1000 bulk 1E10 shear 1E9
struct shell property density 1000 thickness 0.2 isotropic 20E9 0.2
zone face apply velocity-normal 0.0 range position-z 0.0
model gravity 0 0 -10.0
model mechanical active on
model dynamic active off
model largestrain off
model solve elastic
struct link delete range component-id 73
struct link delete range component-id 84
fish define delRecursiveLink
loop foreach nP struct.node.list()
lP = struct.node.link(nP) ; link pointer corresponding the node
oo = io.out("=========================")
oo = io.out("Node pointer: " + string(nP) + " Node ID: " + string(struct.node.id.component(nP)))
if lP != null & struct.node.extra(nP,1) != 'checked' & struct.link.type(lP) = "Structure Node" then ; meet condition (0. node has link 1. not out of bound, 2. previously checked)
arr = array.create(10)
local arrIdx = 1
arr(arrIdx) = struct.link.target(lP)
; oo = io.out(lP)
; io.out("Target Node of Link " + string(lP) + " is " + string(arr(arrIdx)))
vRef = struct.node.pos.reference(nP) ; position of the reference node
; oo = io.out(vRef)
nPNext = struct.node.next(nP) ; nl is node pointer
loop while nPNext != null
; io.out("Node: " + string(nl))
if struct.node.pos.reference(nPNext) = vRef & struct.node.extra(nPNext,1) != 'checked' then ; check node position with the reference node, proceed when same position
struct.node.extra(nPNext,1) = 'checked' ; mark for do not check again
arrIdx = arrIdx + 1
arr(arrIdx) = struct.link.target(struct.node.link(nPNext,1))
; vComp = struct.node.pos.reference(nl)
; io.out("Position" + string(vComp))
io.out("Node " + string(struct.node.id.component(nP)) + " & " + "Node " + string(struct.node.id.component(nPNext)) + " is same position")
io.out(struct.node.link(nPNext,1))
else
; io.out("Skipped")
endif
nPNext = struct.node.next(nPNext) ; move to next node
end_loop
local i = 2
loop while i <= 10
local v = arr(i)
local j = 1
loop while j < i
if arr(j) == v & arr(j) != 0 then
dupNode = v
; io.out("duplicate = " + string(v) + " (at indices " + string(j) + " & " + string(i) + ")")
io.out("Node " + string(dupNode) + " is Recursive" )
; io.out(struct.node.find(dupNode))
io.out("Link No. " + string(struct.node.link(struct.node.find(dupNode))) + " Should be deleted")
endif
j = j + 1
end_loop
i = i + 1
end_loop
else
oo = io.out('Passed : checked before or No link')
endif
endloop
end
@delRecursiveLink