Plotting cracks in 3DEC

In 3DEC, joint failure is associated with subcontacts. However the subcontacts represent points, so it is not easy to plot them as 2D “cracks”. This is different from UDEC where the contacts are lines that can be easily plotted.

Assuming you have a BBM type model (i.e. a model with lots of blocks and contacts, rather than a model with a few large joints), you could group the contacts according to the subcontact failures, and then plot joints and range by the group names. Example FISH function below. This generates the plot shown below for the fragmentation example in the manual.

fish def plot_cracks
  loop foreach cp block.contact.list
    count = 0
    broken = 0
    loop foreach cx block.contact.subcontact(cp)
      count += 1
      if block.subcontact.state(cx) > 0
        broken += 1
      endif
    end_loop

    if broken = count
      block.contact.group(cp) = 'fully-cracked'
    else if broken > 0
      block.contact.group(cp) = 'partially-cracked'
    endif
  end_loop
end
[plot_cracks]

; same function multi-threaded
fish operator plot_cracks_multi(cp)
    local count = 0
    local broken = 0
    loop foreach local cx block.contact.subcontact(cp)
      count += 1
      if block.subcontact.state(cx) > 0
        broken += 1
      endif
    end_loop

    if broken = count
      block.contact.group(cp) = 'fully-cracked'
    else if broken > 0
      block.contact.group(cp) = 'partially-cracked'
    endif
end


[plot_cracks_multi(::block.contact.list)]

2 Likes

Follow up. If you want to plot cracks by failure mode, you can use the code below. Note however that:

  1. This gives the state when the function is called, not when the crack first forms. If you want to record the state when the crack first forms, you would need to use a fish callback with event subcontact_state_change
  2. Generally when a subcontact fails in tension, it will also quickly fail in shear because the cohesion drops to 0 and the frictional force will also be 0 (no normal force). To prevent this, you can specify a residual cohesion that is not 0

fish operator plot_crack_type(cp)
local tensile = 0
local shear = 0
loop foreach local cx block.contact.subcontact(cp)
if math.and(block.subcontact.state(cx),4) # 0
shear += 1
endif
if math.and(block.subcontact.state(cx),8) # 0
tensile += 1
endif
end_loop

if shear > tensile
  block.contact.group(cp) = 'shear'
else if tensile > shear
  block.contact.group(cp) = 'tensile'
else if shear > 0
  block.contact.group(cp) = 'mixed'
endif

end
[plot_crack_type(::block.contact.list)]

1 Like