Packing in a predicate excluding the volume already occupied by spheres

Asked by behzad

Hey guys,

I have a model composed of bunch of clumps and some standalone spheres.

First I create the clumps cloud in the desired volume and then I create the standalone particles packing. The packing can be either random packing (spheres cloud) or regular packing (like orthogonal).
The problem is the spheres packing takes also the volume occupied by the clumps.
Some spheres are completely inside a clump and number of spheres and clumps are big and so using calm() is not the best solution.

Can we kind of exclude the volume occupied by the clumps from the packing generation?

Thank you.

Behzad

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
behzad
Solved:
Last query:
Last reply:
Revision history for this message
Jan Stránský (honzik) said :
#1

Hi Behzad,

as usual, more options are available :-) for example

1) have a look at [1], you can create a predicate for each clump and
"subtract" them from original predicate. I am not sure with the
performance..

2) create the packing as you described and delete the standalone spheres
that interact with clumps

cheers
Jan

PS: a MWE [2] with the commands you are using would not hurt anyway :-)

[1] https://yade-dem.org/doc/user.html#boolean-operations-on-predicates
[2] https://yade-dem.org/wiki/Howtoask

2015-09-01 23:01 GMT+02:00 behzad <email address hidden>:

> New question #270991 on Yade:
> https://answers.launchpad.net/yade/+question/270991
>
>
> Hey guys,
>
> I have a model composed of bunch of clumps and some standalone spheres.
>
> First I create the clumps cloud in the desired volume and then I create
> the standalone particles packing. The packing can be either random packing
> (spheres cloud) or regular packing (like orthogonal).
> The problem is the spheres packing takes also the volume occupied by the
> clumps.
> Some spheres are completely inside a clump and number of spheres and
> clumps are big and so using calm() is not the best solution.
>
> Can we kind of exclude the volume occupied by the clumps from the packing
> generation?
>
> Thank you.
>
> Behzad
>
> --
> You received this question notification because you are a member of
> yade-users, which is an answer contact for Yade.
>
> _______________________________________________
> Mailing list: https://launchpad.net/~yade-users
> Post to : <email address hidden>
> Unsubscribe : https://launchpad.net/~yade-users
> More help : https://help.launchpad.net/ListHelp
>

Revision history for this message
behzad (behzad-majidi) said :
#2

well, the question is how can I define a predicate for each clump? I have hundreds of clumps in random locations and they have irregular shapes.

- As for option (2). I tried this but since its effect of the porosity of the packing (as expected) is too much, I wanted a more efficient packing algorithm.

Thanks for the answer,
Behzad

Revision history for this message
Jan Stránský (honzik) said :
#3

>
> well, the question is how can I define a predicate for each clump? I
> have hundreds of clumps in random locations and they have irregular
> shapes.
>

pred = originalPredicate
for clump in allClumps:
   cPred = makePredicateFromClump(clump)
   # for the help of specific implementation, read [1].
   # "I have hundreds of clumps in random locations and they have
irregular shapes"
is not enough information :-)
   # are the clump members only spheres? if no, what shapes? are they
overlapping or not? ...?
   pred = pred - cPred

>
> - As for option (2). I tried this but since its effect of the porosity
> of the packing (as expected) is too much, I wanted a more efficient
> packing algorithm.
>

Actually the effect of both my answers should be the same. Random or
regular packing are first created for a large volume and then it is cut
according to the predicate (so the same as deleting the intersecting
particles).

If you want dense packing composed of both clumps and spheres, it is a bit
different question.. One option would be to create loose packing of defined
properties and then compress it (e.g. using PeriIsoCompressor or
TriaxialTest).

cheers
Jan

[1] https://yade-dem.org/wiki/Howtoask

Revision history for this message
Bruno Chareyre (bruno-chareyre) said :
#4

A rather simple option could be:
- insert all the clumped spheres in a SpherePack (sp.fromSimulation())
- generate the standalone spheres (sp.makeCloud())

The generated spheres will not overlap.

Revision history for this message
behzad (behzad-majidi) said :
#5

Jan:

Thanks I'll try it.

Bruno:

That's how I generate my clumps cloud:

for i in range(len(temps3050)):
    temps3050[i]=pack.SpherePack()
    temps3050[i].makeCloud((-0.0045,-0.0045,0.0002),(0.0045,0.0045,0.0019),rMean=coke3050[i][0],rRelFuzz=0.0,num=coke3050[i][1])
    O.bodies.append([utils.sphere(c,r, material='coke') for c,r in temps3050[i]])
    O.bodies.replaceByClumps(temps_3050[i],[1.0])

Then, I generate the sphere packing (in this case a regular packing) by:

sp=pack.SpherePack()
pred=pack.inAlignedBox((-0.006,-0.006,0),(0.006,0.006,0.002))

O.bodies.append(pack.regularOrtho(pred,radius=8e-5,gap=1e-8, material='coke'))

Then, how can I use the command fromSimulation()?

Cheers,
Behzad

Revision history for this message
Bruno Chareyre (bruno-chareyre) said :
#6

It doesn't matter how you generate the clumps.
After generating them define an empty SpherePack and put all the clumped spheres in it with sp.fromSimulation().
Then use sp to generate more spheres.

Revision history for this message
behzad (behzad-majidi) said :
#7

check this out:

from yade import utils, plot
from yade import pack, qt

#==========================================
## define the materials

O.materials.append(CohFrictMat(normalCohesion= 1e8, shearCohesion= 1e8, isCohesive= False, young=1.0e4,
density=1530, poisson=0.3, frictionAngle= 0.5,fragile=False,label='coke'))

#========= creating walls ======================

walls=aabbWalls([(-0.006,-0.006,-0.00005),(0.006,0.006,0.002)],thickness=0.0001,oversizeFactor=1.0,material='coke')
wallIds=O.bodies.append(walls)

#================================================================
#===================== Inserting aggregates =====================
#================================================================

radz12= [0.447918e-3,0.631558e-3,0.432997e-3,0.354383e-3,0.644684e-3,0.501349e-3,0.419795e-3,0.305748e-3,0.401928e-3,0.301956e-3]
poz12= [[-0.327852e-3,0.13963e-3,0.0854213e-3],[-0.00642485e-3,0.0540226e-3,0.130283e-3],[-0.0784524e-3,0.131143e-3,0.507045e-3],[0.266248e-3,-0.210016e-3,-0.630071e-3],[-0.0142571e-3,-0.106791e-3,-0.16405e-3],[0.221276e-3,0.213503e-3,0.309049e-3],[0.2366e-3,-0.0271234e-3,-0.29612e-3],[-0.55599e-3,-0.0426141e-3,-0.214846e-3],[0.214827e-3,0.265521e-3,0.442681e-3],[0.376437e-3,0.0275707e-3,0.181478e-3]]
template12= []
template12.append(clumpTemplate(relRadii=radz12,relPositions=poz12))

coke3050=(0.129903989e-03,5)

temps3050=['t']

temps_3050=[template12]

for i in range(len(temps3050)):
    tp=pack.SpherePack()
    tp.makeCloud((-0.0004,-0.0004,0.0002),(0.0004,0.0004,0.0019),rMean=coke3050[0],rRelFuzz=0.0,num=coke3050[1])
    O.bodies.append([utils.sphere(c,r, material='coke') for c,r in tp])
    O.bodies.replaceByClumps(temps_3050[i],[1.0])

############################
### DEFINING ENGINES ###
############################

O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb(),Bo1_Facet_Aabb()]),
 InteractionLoop([Ig2_Sphere_Sphere_ScGeom6D(),Ig2_Box_Sphere_ScGeom6D()],
 [Ip2_CohFrictMat_CohFrictMat_CohFrictPhys(setCohesionNow=True, setCohesionOnNewContacts=True)],
 [Law2_ScGeom_FrictPhys_CundallStrack(),Law2_ScGeom6D_CohFrictPhys_CohesionMoment()]
 ),
 NewtonIntegrator(damping=0.4,gravity=[0,0,-9.81])
]

O.dt=1e-7

#======= creating the sphere packing ============

sp=pack.SpherePack()
sp.fromSimulation()

sp.makeCloud((-0.001,-0.001,0.0),(0.001,0.001,0.002),num=500, rMean=5e-5,rRelFuzz=0.0)

O.bodies.append([utils.sphere(c,r,material='coke') for c,r in sp])

for x in range(len(O.bodies)):
 if (O.bodies[x]):
                if isinstance(O.bodies[x].shape,Sphere):
   if O.bodies[x].isClumpMember:
    O.bodies[x].shape.color=(0.8,0.8,0.0)
   else:
    O.bodies[x].shape.color=(0.1,0.3,0.1)

The clumps become NaN:

O.run(100,True)
O.bodies[21].state.pos

gives: Vector3(nan,nan,nan)

Revision history for this message
Bruno Chareyre (bruno-chareyre) said :
#8

The problem is here:
O.bodies.append([utils.sphere(c,r,material='coke') for c,r in sp])

You need to filter out those spheres which correspond to the initial clumps, else each clump member is inserted again.

The last 500 spheres are
[[[s,r] for s,r in sp][-k-1] for k in range(500)]

So this seems to be ok:
O.bodies.append([utils.sphere(sp[0],sp[1],material='coke') for sp in [[[s,r] for s,r in sp][-k-1] for k in range(500)]])

Revision history for this message
behzad (behzad-majidi) said :
#9

Awesome!
Yeah, it works. Thanks Bruno.