Problem creating clumps from existing spheres

Asked by loiseaurare on 2017-04-26

Hi everybody,

I have been using the agglomerate examples that can be found in the docs from yadedaily, in order to generate a packed sample of clumped particles. In the example this was done in three scripts (Makecloud, divide and compress) , creating at the end of each file a temporary file that was reloaded in the subsequent simulation.

I figured that I would like to have those three scripts all in one go, in order to launch this simulation, have the package and then save it to be used in other simulations.

But I am having trouble when it comes to actually clump assemblies of particle. The strange thing is I haven't been changing much of the existing code !

The code creates a list of groups of spheres, which are to be later on assembled in a clump.
So the spheres are added one after another, based on their agglomerate number, that has been set previously by creating an initial sphere pack, and then packing in each of the spheres another sphere pack. So the agglomerate number would be the id of the initials bigger spheres, I guess.

Once they are all stored in the same occurence of the list, each element of the list ( that is, each group of spheres), is called in order to be clumped.
and then I get this error :

Traceback (most recent call last):
  File "/usr/bin/yadedaily", line 182, in runScript
  File "", line 74, in <module>
IndexError: Body already has id 0 set; appending such body (for the second time) is not allowed.

I am not sure what this means, but it seems like the program is trying to append the spheres once again, when they are already in the simulation. But that results strange to me, since I thought the appendClumped function could work with existing spheres..

Here is the full script :

# -*- coding: utf-8 -*-

from yade import export
from yade import export,ymport
import random

def getClumpInfo():
 for b in O.bodies:
  if b.isClump:
   print 'Clump ',,' has following members:'
   keys = b.shape.members.keys()
   for ii in range(0,len(keys)):
    print '- Body ',keys[ii]
   print 'inertia:',b.state.inertia
   print 'mass:',b.state.mass,'\n'
   print 'no clumps'

dim = (15,15,15) # dimensions for makeCloud
radius = 1
fuzz = 0.2

# use of makeCloud function
sp = pack.SpherePack()
sp.makeCloud((0,0,0), dim, rMean=radius, rRelFuzz=fuzz, seed=1)

random.seed(1) # to make colors always the same

attrs = []

colors = [randomColor() for s in sp]
# each macroparticle is filled randomDensePack
for si,s in enumerate(sp):
 sphere = pack.inSphere(s[0],s[1])
 sp1 = pack.randomDensePack(
  spheresInCell = 500,
  radius = .2,
  memoizeDb = '/tmp/agglomeratepackaux.db',
  returnSpherePack = True,
 ids = sp1.toSimulation(color=colors[si]) # add the result to simulation with uniform color

 for i in ids:
  O.bodies[i].agglomerate = si # tell each particle who is its agglomerate


sp2 = []
for b in O.bodies :

# add walls first
dim = (15,15,15)
walls = aabbWalls(((0,0,0),(dim)))
wallIds = O.bodies.append(walls)

# clump agglomerates
n = max(a for a in attrs)+1
colors = [randomColor() for _ in xrange(n)]
agglomerates = [[] for _ in xrange(n)]

for s,a in zip(sp2,attrs):
        aa = a
 s.agglomerate = aa
 s.shape.color = colors[aa]

for g in agglomerates:

O.engines = [
  thickness = 0,
  stressMask = 7,
  internalCompaction = False,
  label = 'compressor',
O.dt = PWaveTimeStep()

# compress the sample
compressor.goal1 = compressor.goal2 = compressor.goal3 = -1e-7,True)
compressor.goal1 = compressor.goal2 = compressor.goal3 = -1e-5,True)

# save the result, including information of agglomerates which the particle belongs to

 from yade import qt

Welle, if anybody has an idea, it would be of great help !

Question information

English Edit question
Yade Edit question
No assignee Edit question
Solved by:
Last query:
Last reply:
Christian Jakob (jakob-ifgt) said : #1


>for g in agglomerates:
> O.bodies.appendClumped(g)

This will not work as you expect, because appendClumped() function needs a list of body objects as input [1]. In the loop above you try to deliver integer values to the function, which is not working.

You can create a list of bodies, which you want to clump together and use this list for appendClumped() function.


listOfClumpMembers = []
for b in O.bodies:
  if <condition>:




loiseaurare (loiseaurare) said : #2

Hi christian,

thanks for your answer !

However, I thought I was trying to append a list of object, because that is what is stores in each occurence of the agglomerates list, as defined here :

# clump agglomerates
n = max(a for a in attrs) -- > numbers af agglomerates
colors = [randomColor() for _ in xrange(n)]
agglomerates = [[] for _ in xrange(n)] ---> create a list af list with n occurences

for s,a in zip(sp2,attrs): ----> here sp2 is a list of bodies
        aa = a
 s.agglomerate = aa
 s.shape.color = colors[aa]
        agglomerates[aa].append(s) ---> so it's bodies that are appended in each of the agglomerates lists.

Anyway, I actually think I solved my problem. I was explained that actually the function appendClumped appends the bodies that are given as a list, whereas the bodies I wanted to clump where already appended in the simulation ( with the sphereToSimulation function ).

So I used the clump function, which however does not take a list of BODIES, like appendClumped, but a list of IDS of bodies. I didn't get that while reading the documentation, I thought the two functions used the same args, so I didn't succeed in using clump at first.