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