REFD method with clumps, but maintaining the proportion of clumps

Asked by Marcus Moravia

Hello everybody!

I am trying to prepare clumps sample using radius-expansion friction-decrease method. I am using the TriaxialStressController as functional component, like in the tutorial:

https://github.com/yade/trunk/blob/master/examples/triax-tutorial/script-session1.py

I would like to maintain the proportion of clumps during the growth process of the spheres (i.e., by keeping also proportional the distance between the spheres that constitute the clumps), but I do not know how to perform that. Is there an easy way to do this?

Thank you very much,
Marcus.

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Bruno Chareyre
Solved:
Last query:
Last reply:
Revision history for this message
Bruno Chareyre (bruno-chareyre) said :
#1

Hi Marcus,
Is there a reason why you think "maintaining the proportion of clumps" is a problem?
Did you find it was not preserved in the tutorial script? It would be a bug (in this case please show the script).
Bruno

Revision history for this message
Marcus Moravia (mgmoravia) said :
#2

Hi Bruno,

Thank you for your reply. The script below is in the format of the tutorial script. As the number of particles increases, the overlap of the clumps' spheres begins to be more similar to the original geometry. But even with the maximum number of particles supported by the model (i.e., 500 particles), the geometry of the clumps is not the same as that defined in the model. I have no idea about the logic behind the number of particles in this case. Could you help me, please?

### Script ###

from yade import pack

nRead=readParamsFromTable(
  num_particles=100,# number of spheres
  compFricDegree = 30, # contact friction during the confining phase
  key='_triax_base_', # put you simulation's name here
  unknownOk=True
)

from yade.params import table

## Particles
mn,mx = Vector3(0,0,0),Vector3(1,1,1)
key=table.key
num_particles = table.num_particles
radius = .1
damp = 0.2
compFricDegree = table.compFricDegree
young = 5e6
stabilityThreshold = 0.01

## REFD Parameters
targetPorosity = 0.44
finalFricDegree = 30

## Triaxial teste parameters
rate = - 0.02

O.materials.append(FrictMat(young=young,poisson=0.5,frictionAngle=radians(compFricDegree),density=2600,label='sphereMat'))
O.materials.append(FrictMat(young=young,poisson=0.5,frictionAngle=0,density=0,label='wallMat'))

walls=aabbWalls([mn,mx],thickness=0,material='wallMat')
wallIds=O.bodies.append(walls)

sp=pack.SpherePack()

c1=pack.SpherePack([((0,0,0),.03),((.04,0,0),.025),((.025,.03,0),.02),((.025,.01,.03),.02)])
c2=pack.SpherePack([((0,0,0),.036),((.048,0,0),.03),((.03,.036,0),.024),((.03,.012,.036),.024)])
c3=pack.SpherePack([((0,0,0),.024),((.032,0,0),.02),((.02,.024,0),.016),((.02,.008,.024),.016)])
c4=pack.SpherePack([((0,0,0),.042),((.056,0,0),.035),((.035,.042,0),.028),((.035,.014,.042),.028)])
c5=pack.SpherePack([((0,0,0),.018),((.024,0,0),.015),((.015,.018,0),.012),((.015,.006,.018),.012)])
sp=pack.SpherePack()
print 'Generated # of clumps:',sp.makeClumpCloud((0,0,0),(1,1,1),[c1,c2,c3,c4,c5],num=num_particles,periodic=False,seed=1)
sp.toSimulation(material='sphereMat')
O.bodies.updateClumpProperties(discretization=50)

triax=TriaxialStressController(
  maxMultiplier = 1. + 2e4 / young,
  finalMaxMultiplier = 1. + 2e3 / young,
  thickness = 0,
  stressMask = 7,
  internalCompaction = True,
)

newton = NewtonIntegrator(damping=damp)

O.engines=[
  ForceResetter(),
  InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb()]),
  InteractionLoop(
    [Ig2_Sphere_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom()], ## collision geometry
    [Ip2_FrictMat_FrictMat_FrictPhys()], ## collision "physics"
    [Law2_ScGeom_FrictPhys_CundallStrack()] ## set contact law to apply forces
),

GlobalStiffnessTimeStepper(active=1,timeStepUpdateInterval=100,timestepSafetyCoefficient=0.8),
  triax,
  TriaxialStateRecorder(iterPeriod=100,file='WallStresses'+table.key),
  newton,
]

triax.goal1=triax.goal2=triax.goal3 = - 10000

while 1:
  O.run(1000, True)
  unb=unbalancedForce()
  print 'unbalanced force:',unb,' mean stress: ',triax.meanStress
  if unb<stabilityThreshold and abs(- 10000 - triax.meanStress) / 10000 < 0.001:
    break

import sys
while triax.porosity>targetPorosity:
  compFricDegree = 0.95 * compFricDegree
  setContactFriction(radians(compFricDegree))
  print "\r Friction: ",compFricDegree," porosity:",triax.porosity,
  sys.stdout.flush()
  O.run(500,True)

triax.internalCompaction=False
setContactFriction(radians(finalFricDegree))
triax.stressMask = 5
triax.goal2 = rate
triax.goal1 = - 10000
triax.goal3 = - 10000
newton.damping = 0.1

rr=yade.qt.Renderer()
Gl1_Sphere.stripes=True
yade.qt.View()
O.saveTmp()

Revision history for this message
Marcus Moravia (mgmoravia) said :
#3

Hello again,

I have done some scripting checks. Although the source code contemplates homothetic displacements (Shop_02.cpp), using only two clumps with the same geometry in the tutorial script, I was not able to observe this behavior (the code results different overlapping values between the initial condition and after the growth process of the spheres). Moreover, in the simplified script below that consider only the growParticles function (i.e., function used in the TriaxialStressController function), the radius of the spheres that make up the clumps seems to be updated to a value that follows: new_radius=(multiplier^number_of_clumps)*initial_radius.

Thank you for your help.

### Simplified Script ###

O.materials.append(FrictMat(poisson=0.5,density=2600,label='sphereMat'))

from yade import pack

nElem = 7

c=pack.SpherePack([((0,0,0),.003),((.006,0,0),.003)])
sp=pack.SpherePack()
print 'Generated # of clumps:',sp.makeClumpCloud((0,0,0),(10,10,10),[c],num=nElem,periodic=False,seed=1)
sp.toSimulation(material='sphereMat')

for c in O.bodies:
  if c.isClump:
    O.bodies.updateClumpProperties(discretization=250)
    growParticles(multiplier=2)

O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]),
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom()],
  [Ip2_FrictMat_FrictMat_FrictPhys()],
  [Law2_ScGeom_FrictPhys_CundallStrack()]
 ),
 NewtonIntegrator(damping=.4,gravity=(0,0,-9.81)),
# PyRunner(command='volumeClumps()',iterPeriod=50,label='volume')
]

O.dt=.5*PWaveTimeStep()
O.saveTmp()
O.step()
yade.qt.View()

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

Thank you for shortening the script.
It seems you found a bug but I don't understand what happens in details, yet.

If you comment out "O.bodies.updateClumpProperties(discretization=250)" they grow as expected.
It seems the functions growParticles and updateClumpProperties don't play well together.

>a value that follows: new_radius=(multiplier^number_of_clumps)*initial_radius
That's exactly what your algorithm does indeed since you execute growParticles(multiplier=2) as many times as the number of clumps in O.bodies.

Before the bug is fixed I would suggest to not use updateClumpProperties() in your case (you can always change mass/inertia manually if needed), then the problem shoud dispapper.

Regards

Bruno

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

I just found that the the particles were not clumped at all after sp.toSimulation().
The changing overlap is not because they grow, it is because the individual spheres move when O.step().
Not clear why, it still sounds like a bug.
Bruno

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

Ok...
growParticles() is changing positions instantaneously, however some positions stored internally in the clump data are not updated and they are used in NewtonIntegrator. Consequence:
 grow() + step() = update + downdate positions.

The function updateClumpProperties is needed to update the internal clump data. Problem in your case: it was not executed after the last call to glow().
I'll fix the problem by documenting this situation in the grow() function.

I would suggest to use updateClumpProperties(-1) if you grow very frequently (like every 10 timesteps) so that you don't recompute mass/inertia all the time.
Below is a working version of your last script.
Regards
Bruno

O.materials.append(FrictMat(poisson=0.5,density=2600,label='sphereMat'))
from yade import pack
nElem = 7

c=pack.SpherePack([((0,0,0),.003),((.006,0,0),.003)])
sp=pack.SpherePack()
print 'Generated # of clumps:',sp.makeClumpCloud((0,0,0),(10,10,10),[c],num=nElem,periodic=False,seed=1)
sp.toSimulation(material='sphereMat')

growParticles(multiplier=128)
O.bodies.updateClumpProperties(discretization=20)

O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]),
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom()],
  [Ip2_FrictMat_FrictMat_FrictPhys()],
  [Law2_ScGeom_FrictPhys_CundallStrack()]
 ),
 NewtonIntegrator(damping=.4,gravity=(0,0,-9.81)),
]

O.step()
yade.qt.View()

Revision history for this message
Marcus Moravia (mgmoravia) said :
#7

Bruno, I just would like to thank you for all your explanations and suggestions. The Yade source code has many details, but you gave me a great summary of the problem with 'updateClumpProperties'. Thank you again,

Marcus.

Revision history for this message
Marcus Moravia (mgmoravia) said :
#8

Thanks Bruno Chareyre, that solved my question.

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

Hi Marcus,
The problem should be fixed with [1].
It is no longer needed to updateProperties (hence the TriaxialController
method should also work).
Let me know if you find other related issues.
Cheers
Bruno

[1]
https://github.com/yade/trunk/commit/243ee130ba97e628763d36c1b2442700e38d9185

Revision history for this message
Marcus Moravia (mgmoravia) said :
#10

Hi Bruno,
I have compiled the Yade code with this fix and tested the TriaxialController with clumps. Everything seems to work fine so far. I am going to work with this version and I will let you know in case I find any other issue.
I really appreciate you,
Marcus.