Contacts between walls and particles

Asked by Sanel Avdić

Hi everyone, I'm new at YADE.
I am trying to simulate uniaxial compression. I have a rigid cylinder filled with particles and then I'm using rigid plane to perform compression. My goal is to get the goal distribution along the z-axis of the cylinder. I was planning to obtain all particles that are in contact with the cylinder wall and then extract their positions and forces in .txt file and then somehow get the load distribution. Can anyone help me with the part where i need to find IDs of particles that are in contact with the wall? Or, even better, are there any more simple solutions for this?
Thanks in advance!

Definition of cylinder walls and particle filling:
O.bodies.append(geom.facetCylinder((a/2,a/2,3*b/2), a,3*b, wallMask=6))
sp = pack.SpherePack()
sp.makeCloud((0, 0, 0), (0.03, 0.03, 8*b/3), rMean=rMean, rRelFuzz=rRelFuzz)
sp.toSimulation(material='spheres')

Question information

Language:
English Edit question
Status:
Answered
For:
Yade Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:

This question was reopened

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

Hello,

> I'm new at YADE

welcome :-)

The task sounds as not difficult.
please provide a MWE [1].
It should then be easy for us to give you specific advice(s) and/or directly adjust the code to do what you are expecting.

Cheers
Jan

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

Revision history for this message
Sanel Avdić (avdic99) said :
#3

Here is the script I'm using. The simulation is working. I need help to build a part of the code that will give me an access to all inter-particle forces with particle IDs and positions so I can extract the ones that are acting on the cylinder walls. It would be great if i can extract the data for certain values of the compression force Fz (every 100N for example).
Thanks!

#variables
rMean=0.0025
rRelFuzz=0.2
maxLoad=800
minLoad=100
a=0.025
b=2*a
c=0.03
g=9.81

#material definiton
O.materials.append(FrictMat(young=5e6, poisson=.5, frictionAngle=radians(27), density=1000, label='spheres'))

#cylinder walls + particles creation
from yade import pack, plot
O.bodies.append(geom.facetCylinder((a/2,a/2,5*b), a,10*b, segmentsNumber=100, wallMask=6))
sp = pack.SpherePack()
sp.makeCloud((0, 0, 0), (c, c, 28*b/3), rMean=rMean, rRelFuzz=rRelFuzz)
sp.toSimulation(material='spheres')

#engines
O.engines = [
        ForceResetter(),
        InsertionSortCollider([Bo1_Sphere_Aabb(), Bo1_Facet_Aabb(), Bo1_Wall_Aabb()]),
        InteractionLoop(
                [Ig2_Sphere_Sphere_ScGeom(), Ig2_Facet_Sphere_ScGeom(), Ig2_Wall_Sphere_ScGeom()],
                [Ip2_FrictMat_FrictMat_MindlinPhys()],
                [Law2_ScGeom_MindlinPhys_Mindlin()]
        ),
        NewtonIntegrator(gravity=(0, 0, -9.81), damping=0.5),
        PyRunner(command='checkUnbalanced()', realPeriod=2, label='checker'),
]

#timestep
O.dt = .3 * PWaveTimeStep()

#energytracking
O.trackEnergy = True
Etot=O.energy.total()

#settling and pressing the particles
def checkUnbalanced():
 if O.iter < 30000:
  return
 if unbalancedForce() > 0.1:
  return

 O.bodies.append(wall(max([b.state.pos[2] + b.shape.radius for b in O.bodies if isinstance(b.shape, Sphere)]), axis=2, sense=-1))
 global plate
 plate = O.bodies[-1]
 plate.state.vel =(0,0,-0.1)
 O.engines = O.engines + [PyRunner(command='addPlotData()', iterPeriod=100)]
 checker.command = 'unloadPlate()'

#unloading the particles
def unloadPlate():
 if abs(O.forces.f(plate.id)[2]) >= maxLoad:
  plate.state.vel *= -1
  checker.command = 'stopUnloading()'

#finishing the simulation
def stopUnloading():
 if abs(O.forces.f(plate.id)[2]) < minLoad:
  plate.state.vel *= -1
  plot.saveDataTxt(O.tags['d.id'] + '.txt')
  O.pause()

#plotting the data
def addPlotData():
 if not isinstance(O.bodies[-1].shape, Wall):
  plot.addData()
  return
 Fz = O.forces.f(plate.id)[2]
 plot.addData(Fz=Fz, w=plate.state.pos[2], unbalanced=unbalancedForce(), i=O.iter, Etot=O.energy.total() )

yade.qt.Renderer().shape=0
yade.qt.Renderer().intrPhys=1
plot.plots = {'w': ('Fz',), 'i':('Etot'),}
plot.plot()

O.run()
waitIfBatch()

Revision history for this message
Jérôme Duriez (jduriez) said :
#4

Hi,

As a hint, O.interactions.withBody (to apply to all IDs of facets forming your walls) should probably help:

https://yade-dem.org/doc/yade.wrapper.html#yade.wrapper.InteractionContainer.withBody

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

Hello,

using Jerome's hint:
###
def extractContacts():
    facets = [b for b in O.bodies if isinstance(b.shape,Facet)]
    interactions = [interaction for facet in facets for interaction in O.interactions.withBody(facet.id)]
    contacts = [(
        i.geom.contactPoint,
        i.phys.normalForce + i.phys.shearForce,
    ) for i in interactions]
    return contacts
###

Cheers
Jan

Revision history for this message
Sanel Avdić (avdic99) said :
#6

Thanks Jan Stránský, that solved my question.

Revision history for this message
Sanel Avdić (avdic99) said :
#7

Hello,

Regarding to this, as my cylindrical facet is made of many segments, during post processing (force chain) I saw that there are particles that are in contact with more than one segment, and there is force drawn for each segment that is in contact with that particle. I'm wondering if each of these contacts is caught as an independent contact with the previous function because that would affect my results (as I'm averaging the force along z-axis eg. for 0.01<zcoord<0.02 force=sum forces/ number of contacts)?

Thanks

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

> there are particles that are in contact with more than one segment

yes, this is a feature of using plain facets with common edge (or basically "close" to each other).
Each contact is independent.

Cheers
Jan

Can you help with this problem?

Provide an answer of your own, or ask Sanel Avdić for more information if necessary.

To post a message you must log in.