Change colour of spheres when based on Movement

Asked by Clinton Schramm

Hey Guys
New to Yade, been building a model for a tunnel simulation. What i'm trying to acheieve is have the spheres change colour based on there displacement so that I can see where the movement is occuring. Not sure if it's necessary to post the whole code?

Right now the line I am using is

for s in O.bodies:
  s.shape.color=scalarOnColorScale(0.1*s.state.displ().norm(),0,0)

What currently happens is the spheres change colour, but only initially. Is this the right code to do that? Could someone explain what this code is actually doing?

Question information

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

Hello,

Yade (Python) goes through the script and executes line by line. If you
have it like that in your script (once), then it is executed just once.

To execute is regulary, use PyRunner [1] in your engines:

#########################
def colorSpheres():
  for s in O.bodies:
    s.shape.color = ....

O.engines = [
  ...
  PyRunner(iterPeriod=100,command="colorSpheres()"), # you can use
realPeriod or virtPeriod instead of irerPeriod
]
#########################

cheers
Jan

[1] https://yade-dem.org/doc/yade.wrapper.html#yade.wrapper.PyRunner

2016-05-28 12:56 GMT+02:00 Clinton Schramm <
<email address hidden>>:

> New question #294531 on Yade:
> https://answers.launchpad.net/yade/+question/294531
>
> Hey Guys
> New to Yade, been building a model for a tunnel simulation. What i'm
> trying to acheieve is have the spheres change colour based on there
> displacement so that I can see where the movement is occuring. Not sure if
> it's necessary to post the whole code?
>
> Right now the line I am using is
>
> for s in O.bodies:
>
> s.shape.color=scalarOnColorScale(0.1*s.state.displ().norm(),0,0)
>
> What currently happens is the spheres change colour, but only initially.
> Is this the right code to do that? Could someone explain what this code is
> actually doing?
>
>
>
> --
> You received this question notification because your team yade-users 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
Clinton Schramm (clintonschramm) said :
#2

Hi Jan

Thanks for the prompt reply. I have already placed the code within Pyrunner, and still get the same results. I'll post my code below (it is just a modified Odometer Example code with the change sphere colour). Can you see any reason why it shouldn't be working?

# load parameters from file if run in batch
# default values are used if not run from batch
readParamsFromTable(rMean=.05,rRelFuzz=.3,maxLoad=1e6,minLoad=1e4)
# make rMean, rRelFuzz, maxLoad accessible directly as variables later
from yade.params.table import *

# create box with free top, and ceate loose packing inside the box
from yade import pack, plot
O.bodies.append(geom.facetBox((.5,.5,.5),(.5,.5,.5),wallMask=31))
sp=pack.SpherePack()
sp.makeCloud((0,0,0),(1,1,1),rMean=rMean,rRelFuzz=rRelFuzz)
sp.toSimulation()

O.engines=[
   ForceResetter(),
   # sphere, facet, wall
   InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb(),Bo1_Wall_Aabb()]),
   InteractionLoop(
      # the loading plate is a wall, we need to handle sphere+sphere, sphere+facet, sphere+wall
      [Ig2_Sphere_Sphere_L3Geom(),Ig2_Facet_Sphere_L3Geom(),Ig2_Wall_Sphere_L3Geom()],
      [Ip2_FrictMat_FrictMat_FrictPhys()],
      [Law2_L3Geom_FrictPhys_ElPerfPl()]
   ),
   NewtonIntegrator(gravity=(0,0,-9.81),damping=0.5),
   # the label creates an automatic variable referring to this engine
   # we use it below to change its attributes from the functions called
   PyRunner(command='checkUnbalanced()',realPeriod=2,label='checker'),
]
O.dt=.5*PWaveTimeStep()

# the following checkUnbalanced, unloadPlate and stopUnloading functions are all called by the 'checker'
# (the last engine) one after another; this sequence defines progression of different stages of the
# simulation, as each of the functions, when the condition is satisfied, updates 'checker' to call
# the next function when it is run from within the simulation next time

# check whether the gravity deposition has already finished
# if so, add wall on the top of the packing and start the oedometric test
def checkUnbalanced():
   # at the very start, unbalanced force can be low as there is only few contacts, but it does not mean the packing is stable
   if O.iter<5000: return
   # the rest will be run only if unbalanced is < .1 (stabilized packing)
   if unbalancedForce()>.1: return
   # add plate at the position on the top of the packing
   # the maximum finds the z-coordinate of the top of the topmost particle
   for s in O.bodies
  s.shape.color=scalarOnColorScale(s.state.displ().norm(),0,1)
  print 0.1*s.state.displ() #Check to see if repeating
   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 # without this line, the plate variable would only exist inside this function
   plate=O.bodies[-1] # the last particles is the plate
   # Wall objects are "fixed" by default, i.e. not subject to forces
   # prescribing a velocity will therefore make it move at constant velocity (downwards)
   plate.state.vel=(0,0,-.1)
   # start plotting the data now, it was not interesting before
   O.engines=O.engines+[PyRunner(command='addPlotData()',iterPeriod=200)]
   # next time, do not call this function anymore, but the next one (unloadPlate) instead
   checker.command='unloadPlate()'

def unloadPlate():
   # if the force on plate exceeds maximum load, start unloading
   if abs(O.forces.f(plate.id)[2])>maxLoad:
      plate.state.vel*=-1
      # next time, do not call this function anymore, but the next one (stopUnloading) instead
      checker.command='stopUnloading()'

def stopUnloading():
   if abs(O.forces.f(plate.id)[2])<minLoad:
      # O.tags can be used to retrieve unique identifiers of the simulation
      # if running in batch, subsequent simulation would overwrite each other's output files otherwise
      # d (or description) is simulation description (composed of parameter values)
      # while the id is composed of time and process number
      plot.saveDataTxt(O.tags['d.id']+'.txt')
      O.pause()

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]-plate.state.refPos[2],unbalanced=unbalancedForce(),i=O.iter)

# besides unbalanced force evolution, also plot the displacement-force diagram
plot.plots={'i':('unbalanced',),'w':('Fz',)}
plot.plot()

O.run()

Revision history for this message
Clinton Schramm (clintonschramm) said :
#3

Sorry ignore that previous post. It is a bad example and obviously isn't running the way it was supposed to. Here is the actual problem code.

readParamsFromTable(rMean=.01,rRelFuzz=.003,maxLoad=1e5,minLoad=1e4)
# make rMean, rRelFuzz, maxLoad accessible directly as variables later
from yade.params.table import *
numspherespack1=1000
numspherespack2 = 173
Zextentbox = 0.200
width = 0.154
length = 0.441
cylinderheight = 0.130
cylinderradius = 0.05
nosides = 10

#Set materials for spheres, and box
O.materials.append(FrictMat(young=78.71e6,poisson=0.27,frictionAngle=.5934,density=2600,label='spheres')) #Need to find youngs modulus
O.materials.append(FrictMat(young=30e9,poisson=0.2,frictionAngle=0,label='walls'))

# create box with free top, and ceate loose packing inside the box
from yade import pack, plot
O.bodies.append(geom.facetBox((0,0,0),(width/2,length/2,Zextentbox),wallMask=31,material='walls')) #(centre),(x,y,z) Old Box with correct dimensions
TBM=O.bodies.append(geom.facetCylinder(center=(-0.077,.1555,-.100),radius=cylinderradius,height=cylinderheight,orientation=Quaternion((1,0,0),3.1415926/2),segmentsNumber=nosides,wallMask=7,angleRange=None,closeGap=False,wire=False,highlight=False))

sp=pack.SpherePack()
sp.makeCloud((-0.077,0.180,-0.200),(0.077,-0.200,-0.155),rMean=rMean,rRelFuzz=rRelFuzz,num=numspherespack2) #Cloud for under tunnel
#May need to make cloud larger tos full up the model
sp.makeCloud((-0.077,0.180,-0.05),(0.077,-0.180,0.550),rMean=rMean,rRelFuzz=rRelFuzz,num=numspherespack1) #Move cloud in +z 400
sp.toSimulation(material='spheres',color=(0,1,1))

O.engines=[
   ForceResetter(),
   # sphere, facet, wall
   InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb(),Bo1_Facet_Aabb(),Bo1_Wall_Aabb()]),
   InteractionLoop(
      # the loading plate is a wall, we need to handle sphere+sphere, sphere+facet, sphere+wall
      [Ig2_Sphere_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom(),Ig2_Wall_Sphere_ScGeom()],
      [Ip2_FrictMat_FrictMat_FrictPhys()],
      [Law2_ScGeom_FrictPhys_CundallStrack()]
   ),
   NewtonIntegrator(gravity=(0,0,-9.81),damping=0.5),
   #SnapshotEngine(iterPeriod=300,fileBase='/home/clinton/Desktop/Video/1/Centri-',label='cent'),
   # the label creates an automatic variable referring to this engines
   PyRunner(command='checkUnbalanced1()',iterPeriod = 200,label='checker'),
]
O.dt=.5*PWaveTimeStep()

# the following checkUnbalanced, unloadPlate and stopUnloading functions are all called by the 'checker'
# (the last engine) one after another; this sequence defines progression of different stages of the
# simulation, as each of the functions, when the condition is satisfied, updates 'checker' to call
# the next function when it is run from within the simulation next time

# check whether the gravity deposition has already finished
# if so, add wall on the top of the packing and start the oedometric test
def checkUnbalanced1():
   # at the very start, unbalanced force can be low as there is only few contacts, but it does not mean the packing is stable
   if O.iter<5000: return
   # the rest will be run only if unbalanced is < .1 (stabilized packing)
   if unbalancedForce()>.1: return
   # add plate at the position on the top of the packing
   # the maximum finds the z-coordinate of the top of the topmost particle
   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,material='walls'))
   global plate # without this line, the plate variable would only exist inside this function
   plate=O.bodies[-1] # the last particles is the plate
   # Wall objects are "fixed" by default, i.e. not subject to forces
   # prescribing a velocity will therefore make it move at constant velocity (downwards)
   plate.state.vel=(0,0,-.7)
   # start plotting the data now, it was not interesting before
   #O.engines=O.engines+[PyRunner(command='addPlotData()',iterPeriod=200)]
   # next time, do not call this function anymore, but the next one (unloadPlate) instead
   checker.command='unloadPlate1()'

def unloadPlate1():
   # if the force on plate exceeds maximum load, start unloading
   if abs(O.forces.f(plate.id)[2])>maxLoad :
      plate.state.vel*=-3
      # next time, do not call this function anymore, but the next one (stopUnloading) instead
      checker.command='stopUnloading()'

def stopUnloading():

   if abs(O.forces.f(plate.id)[2])<minLoad:
 plate.state.vel*=0
 areacylinder = (.5*nosides*cylinderradius**2*(sin(degrees(360)/10)))/2
 Volcylinder = areacylinder*cylinderheight
        height = max([b.state.pos[2]+b.shape.radius for b in O.bodies if isinstance(b.shape,Sphere)])+Zextentbox
 print 'Height of heighest sphere is: ',height
 v1=Volcylinder+sum([4./3.*pi*(b.shape.radius)**3. for b in O.bodies if isinstance(b.shape,Sphere)])
 v2=width*length*height
 Voidratio=(v2-v1)/v2*100.
 print'The Void Ratio:',Voidratio,'%','This is the second one'

     checker.command='checkUnbalancedtunnelmovement()'

def checkUnbalancedtunnelmovement():
 O.engines=O.engines+[TranslationEngine(translationAxis=[0,1,0],velocity=.08,ids=TBM)]
 # start plotting the data now, it was not interesting before
    #O.engines=O.engines+[PyRunner(command='addPlotDataForceTunnel()',iterPeriod=200)]
 # we use it below to changefor s in O.bodies if isinstance(s.shape,Sphere):
 global CylinderforceX, CylinderforceY, CylinderforceZ

 for s in O.bodies:
  s.shape.color=scalarOnColorScale(s.state.displ().norm(),0,1)
  #print 0.1*s.state.displ()
  #s.shape.color=scalarOnColorScale(0.1*s.state.displ().norm(),0.1*s.state.displ().norm(),0.1*s.state.displ().norm())
  # for changing color based on the movement of sheres. its attributes from the functions called
  #print 'Change'
    CylinderforceX = utils.sumForces([10,14,16,22,26,30,34,36,42,46],(1,0,0))
 CylinderforceY = utils.sumForces([10,14,16,22,26,30,34,36,42,46],(0,1,0))
 CylinderforceZ = utils.sumForces([10,14,16,22,26,30,34,36,42,46],(0,0,1))

 #Cylindernormalforce = sumFacetNormalForces([10,14,16,22,26,30,34,36,42,46],1)
 print 'The sum of normal forces are: ',Cylindernormalforce

 plot.addData(CylinderforceX=CylinderforceX,tx=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),CylinderforceY=CylinderforceY,ty=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),CylinderforceZ=CylinderforceZ,tz=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),Cylindernormalforce=Cylindernormalforce,t=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),i=O.iter)
    # start plotting the data now, it was not interesting before
    #O.engines=O.engines+[PyRunner(command='addPlotDataForceTunnel()',iterPeriod=200)]
    # next time, do not call this function anymore, but the next one (unloadPlate) instead
    #O.pause()

#plot.saveDataTxt(O.tags['d.id']+'.txt')

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]-plate.state.refPos[2],unbalanced=unbalancedForce(),i=O.iter)

#Plotting the force on the tunnel face
def addPlotDataForceTunnel():
  print 'test => ',CylinderforceX
  plot.addData(CylinderforceX,tx=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),i=O.iter)

# besides unbalanced force evolution, also plot the displacement-force diagram
plot.plots={'tx':('CylinderforceX',),'ty':('CylinderforceY',),'tz':('CylinderforceZ',),'t':('Cylindernormalforce',)}
#plot.plots={'i':('unbalanced',),'w':('Fz',),'tx':('Facex',)}

plot.plot()

#O.saveTmp()
from yade import qt
v=qt.View()
v.eyePosition=(-1,0.3,0.25);v.upVector=(0,0,1); v.lookAt=(0,0,0); v.axes=False; v.sceneRadius=1.9

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

Hi Clinton,
create a separate function and separate PyRunner with desired period for
coloring your particles. Then everything works as expected :-) Do not put
it inside functions of totally different purpose.
In your first example, checkUnbalanced was called 2x in my case, in your
second example checkUnbalancedtunnelmovement was called not even once.
Hence no changes were visible
cheers
Jan

2016-05-29 1:32 GMT+02:00 Clinton Schramm <
<email address hidden>>:

> Question #294531 on Yade changed:
> https://answers.launchpad.net/yade/+question/294531
>
> Clinton Schramm gave more information on the question:
> Sorry ignore that previous post. It is a bad example and obviously isn't
> running the way it was supposed to. Here is the actual problem code.
>
> readParamsFromTable(rMean=.01,rRelFuzz=.003,maxLoad=1e5,minLoad=1e4)
> # make rMean, rRelFuzz, maxLoad accessible directly as variables later
> from yade.params.table import *
> numspherespack1=1000
> numspherespack2 = 173
> Zextentbox = 0.200
> width = 0.154
> length = 0.441
> cylinderheight = 0.130
> cylinderradius = 0.05
> nosides = 10
>
> #Set materials for spheres, and box
> O.materials.append(FrictMat(young=78.71e6,poisson=0.27,frictionAngle=.5934,density=2600,label='spheres'))
> #Need to find youngs modulus
>
> O.materials.append(FrictMat(young=30e9,poisson=0.2,frictionAngle=0,label='walls'))
>
> # create box with free top, and ceate loose packing inside the box
> from yade import pack, plot
> O.bodies.append(geom.facetBox((0,0,0),(width/2,length/2,Zextentbox),wallMask=31,material='walls'))
> #(centre),(x,y,z) Old Box with correct dimensions
>
> TBM=O.bodies.append(geom.facetCylinder(center=(-0.077,.1555,-.100),radius=cylinderradius,height=cylinderheight,orientation=Quaternion((1,0,0),3.1415926/2),segmentsNumber=nosides,wallMask=7,angleRange=None,closeGap=False,wire=False,highlight=False))
>
> sp=pack.SpherePack()
> sp.makeCloud((-0.077,0.180,-0.200),(0.077,-0.200,-0.155),rMean=rMean,rRelFuzz=rRelFuzz,num=numspherespack2)
> #Cloud for under tunnel
> #May need to make cloud larger tos full up the model
> sp.makeCloud((-0.077,0.180,-0.05),(0.077,-0.180,0.550),rMean=rMean,rRelFuzz=rRelFuzz,num=numspherespack1)
> #Move cloud in +z 400
> sp.toSimulation(material='spheres',color=(0,1,1))
>
> O.engines=[
> ForceResetter(),
> # sphere, facet, wall
>
> InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb(),Bo1_Facet_Aabb(),Bo1_Wall_Aabb()]),
> InteractionLoop(
> # the loading plate is a wall, we need to handle sphere+sphere,
> sphere+facet, sphere+wall
>
> [Ig2_Sphere_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom(),Ig2_Wall_Sphere_ScGeom()],
> [Ip2_FrictMat_FrictMat_FrictPhys()],
> [Law2_ScGeom_FrictPhys_CundallStrack()]
> ),
> NewtonIntegrator(gravity=(0,0,-9.81),damping=0.5),
>
> #SnapshotEngine(iterPeriod=300,fileBase='/home/clinton/Desktop/Video/1/Centri-',label='cent'),
> # the label creates an automatic variable referring to this engines
> PyRunner(command='checkUnbalanced1()',iterPeriod = 200,label='checker'),
> ]
> O.dt=.5*PWaveTimeStep()
>
> # the following checkUnbalanced, unloadPlate and stopUnloading functions
> are all called by the 'checker'
> # (the last engine) one after another; this sequence defines progression
> of different stages of the
> # simulation, as each of the functions, when the condition is satisfied,
> updates 'checker' to call
> # the next function when it is run from within the simulation next time
>
> # check whether the gravity deposition has already finished
> # if so, add wall on the top of the packing and start the oedometric test
> def checkUnbalanced1():
> # at the very start, unbalanced force can be low as there is only few
> contacts, but it does not mean the packing is stable
> if O.iter<5000: return
> # the rest will be run only if unbalanced is < .1 (stabilized packing)
> if unbalancedForce()>.1: return
> # add plate at the position on the top of the packing
> # the maximum finds the z-coordinate of the top of the topmost particle
> 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,material='walls'))
> global plate # without this line, the plate variable would only
> exist inside this function
> plate=O.bodies[-1] # the last particles is the plate
> # Wall objects are "fixed" by default, i.e. not subject to forces
> # prescribing a velocity will therefore make it move at constant
> velocity (downwards)
> plate.state.vel=(0,0,-.7)
> # start plotting the data now, it was not interesting before
> #O.engines=O.engines+[PyRunner(command='addPlotData()',iterPeriod=200)]
> # next time, do not call this function anymore, but the next one
> (unloadPlate) instead
> checker.command='unloadPlate1()'
>
> def unloadPlate1():
> # if the force on plate exceeds maximum load, start unloading
> if abs(O.forces.f(plate.id)[2])>maxLoad :
> plate.state.vel*=-3
> # next time, do not call this function anymore, but the next one
> (stopUnloading) instead
> checker.command='stopUnloading()'
>
> def stopUnloading():
>
> if abs(O.forces.f(plate.id)[2])<minLoad:
> plate.state.vel*=0
> areacylinder =
> (.5*nosides*cylinderradius**2*(sin(degrees(360)/10)))/2
> Volcylinder = areacylinder*cylinderheight
> height = max([b.state.pos[2]+b.shape.radius for b in O.bodies if
> isinstance(b.shape,Sphere)])+Zextentbox
> print 'Height of heighest sphere is: ',height
> v1=Volcylinder+sum([4./3.*pi*(b.shape.radius)**3. for b in
> O.bodies if isinstance(b.shape,Sphere)])
> v2=width*length*height
> Voidratio=(v2-v1)/v2*100.
> print'The Void Ratio:',Voidratio,'%','This is the second one'
>
> checker.command='checkUnbalancedtunnelmovement()'
>
> def checkUnbalancedtunnelmovement():
>
> O.engines=O.engines+[TranslationEngine(translationAxis=[0,1,0],velocity=.08,ids=TBM)]
> # start plotting the data now, it was not interesting before
>
> #O.engines=O.engines+[PyRunner(command='addPlotDataForceTunnel()',iterPeriod=200)]
> # we use it below to changefor s in O.bodies if
> isinstance(s.shape,Sphere):
> global CylinderforceX, CylinderforceY, CylinderforceZ
>
> for s in O.bodies:
>
> s.shape.color=scalarOnColorScale(s.state.displ().norm(),0,1)
> #print 0.1*s.state.displ()
>
> #s.shape.color=scalarOnColorScale(0.1*s.state.displ().norm(),0.1*s.state.displ().norm(),0.1*s.state.displ().norm())
> # for changing color based on the movement of sheres. its
> attributes from the functions called
> #print 'Change'
> CylinderforceX =
> utils.sumForces([10,14,16,22,26,30,34,36,42,46],(1,0,0))
> CylinderforceY =
> utils.sumForces([10,14,16,22,26,30,34,36,42,46],(0,1,0))
> CylinderforceZ =
> utils.sumForces([10,14,16,22,26,30,34,36,42,46],(0,0,1))
>
> #Cylindernormalforce =
> sumFacetNormalForces([10,14,16,22,26,30,34,36,42,46],1)
> print 'The sum of normal forces are: ',Cylindernormalforce
>
>
> plot.addData(CylinderforceX=CylinderforceX,tx=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),CylinderforceY=CylinderforceY,ty=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),CylinderforceZ=CylinderforceZ,tz=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),Cylindernormalforce=Cylindernormalforce,t=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),i=O.iter)
> # start plotting the data now, it was not interesting before
>
> #O.engines=O.engines+[PyRunner(command='addPlotDataForceTunnel()',iterPeriod=200)]
> # next time, do not call this function anymore, but the next one
> (unloadPlate) instead
> #O.pause()
>
> #plot.saveDataTxt(O.tags['d.id']+'.txt')
>
>
>
> 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]-plate.state.refPos[2],unbalanced=unbalancedForce(),i=O.iter)
>
> #Plotting the force on the tunnel face
> def addPlotDataForceTunnel():
> print 'test => ',CylinderforceX
>
> plot.addData(CylinderforceX,tx=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),i=O.iter)
>
>
>
> # besides unbalanced force evolution, also plot the displacement-force
> diagram
>
> plot.plots={'tx':('CylinderforceX',),'ty':('CylinderforceY',),'tz':('CylinderforceZ',),'t':('Cylindernormalforce',)}
> #plot.plots={'i':('unbalanced',),'w':('Fz',),'tx':('Facex',)}
>
> plot.plot()
>
>
> #O.saveTmp()
> from yade import qt
> v=qt.View()
> v.eyePosition=(-1,0.3,0.25);v.upVector=(0,0,1); v.lookAt=(0,0,0);
> v.axes=False; v.sceneRadius=1.9
>
> --
> You received this question notification because your team yade-users 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
Clinton Schramm (clintonschramm) said :
#5

Thank you again Jan. I have done what you said, but still I can cannot see the spheres changing color.

If I put the pyrunner('Changecolor') in the main engine, it does change the spheres, how ever I need the spheres to change colour only after the cylinder is given it's velocity.

To work around this I tried calling a pyrunner after this piece of code was started. It is below, and sadly doesn't work. I think the procedure of code implementation is correct though?

Another method I thought was running the code in the main engine, and then setting the spheres to the base color just before the cylinder was initiated but this did not seem to work either.

readParamsFromTable(rMean=.03,rRelFuzz=.003,maxLoad=1e5,minLoad=1e4)
# make rMean, rRelFuzz, maxLoad accessible directly as variables later
from yade.params.table import *
numspherespack1=1000
numspherespack2 = 173
Zextentbox = 0.600 #was .200
width = 0.154
length = 0.441
cylinderheight = 0.130
cylinderradius = 0.05
nosides = 10

#Set materials for spheres, and box
O.materials.append(FrictMat(young=78.71e6,poisson=0.27,frictionAngle=.5934,density=2600,label='spheres')) #Need to find youngs modulus
O.materials.append(FrictMat(young=30e9,poisson=0.2,frictionAngle=0,label='walls'))

# create box with free top, and ceate loose packing inside the box
from yade import pack, plot
O.bodies.append(geom.facetBox((0,0,0),(width/2,length/2,Zextentbox),wallMask=31,material='walls')) #(centre),(x,y,z) Old Box with correct dimensions
TBM=O.bodies.append(geom.facetCylinder(center=(-0.077,.1555,-.100),radius=cylinderradius,height=cylinderheight,orientation=Quaternion((1,0,0),3.1415926/2),segmentsNumber=nosides,wallMask=7,angleRange=None,closeGap=False,wire=False,highlight=False))

sp=pack.SpherePack()
sp.makeCloud((-0.077,0.180,-0.200),(0.077,-0.200,-0.155),rMean=rMean,rRelFuzz=rRelFuzz,num=numspherespack2) #Cloud for under tunnel
#May need to make cloud larger tos full up the model
sp.makeCloud((-0.077,0.180,-0.05),(0.077,-0.180,1),rMean=rMean,rRelFuzz=rRelFuzz,num=numspherespack1) #Move cloud in +z 400
sp.toSimulation(material='spheres',color=(0,1,1))

O.engines=[
   ForceResetter(),
   # sphere, facet, wall
   InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb(),Bo1_Facet_Aabb(),Bo1_Wall_Aabb()]),
   InteractionLoop(
      # the loading plate is a wall, we need to handle sphere+sphere, sphere+facet, sphere+wall
      [Ig2_Sphere_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom(),Ig2_Wall_Sphere_ScGeom()],
      [Ip2_FrictMat_FrictMat_FrictPhys()],
      [Law2_ScGeom_FrictPhys_CundallStrack()]
   ),
   NewtonIntegrator(gravity=(0,0,-9.81),damping=0.5),
   SnapshotEngine(iterPeriod=300,fileBase='/home/clinton/Desktop/Video/1/Centri-',label='cent'),
   # the label creates an automatic variable referring to this engines
   PyRunner(command='checkUnbalanced1()',iterPeriod = 200,label='checker'),
   #PyRunner(command='Changecolor()',iterPeriod = 200),
]
O.dt=.5*PWaveTimeStep()

# the following checkUnbalanced, unloadPlate and stopUnloading functions are all called by the 'checker'
# (the last engine) one after another; this sequence defines progression of different stages of the
# simulation, as each of the functions, when the condition is satisfied, updates 'checker' to call
# the next function when it is run from within the simulation next time

# check whether the gravity deposition has already finished
# if so, add wall on the top of the packing and start the oedometric test
def checkUnbalanced1():
   # at the very start, unbalanced force can be low as there is only few contacts, but it does not mean the packing is stable
   if O.iter<5000: return
   # the rest will be run only if unbalanced is < .1 (stabilized packing)
   if unbalancedForce()>.1: return
   # add plate at the position on the top of the packing
   # the maximum finds the z-coordinate of the top of the topmost particle
   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,material='walls'))
   global plate # without this line, the plate variable would only exist inside this function
   plate=O.bodies[-1] # the last particles is the plate
   # Wall objects are "fixed" by default, i.e. not subject to forces
   # prescribing a velocity will therefore make it move at constant velocity (downwards)
   plate.state.vel=(0,0,-.7)
   # start plotting the data now, it was not interesting before
   #O.engines=O.engines+[PyRunner(command='addPlotData()',iterPeriod=200)]
   # next time, do not call this function anymore, but the next one (unloadPlate) instead
   checker.command='unloadPlate1()'

def unloadPlate1():
   # if the force on plate exceeds maximum load, start unloading
   if abs(O.forces.f(plate.id)[2])>maxLoad :
      plate.state.vel*=-3
      # next time, do not call this function anymore, but the next one (stopUnloading) instead
      checker.command='stopUnloading()'

def stopUnloading():

   if abs(O.forces.f(plate.id)[2])<minLoad:
 plate.state.vel*=0
 areacylinder = (.5*nosides*cylinderradius**2*(sin(degrees(360)/10)))/2
 Volcylinder = areacylinder*cylinderheight
        height = max([b.state.pos[2]+b.shape.radius for b in O.bodies if isinstance(b.shape,Sphere)])+Zextentbox
 print 'Height of heighest sphere is: ',height
 v1=Volcylinder+sum([4./3.*pi*(b.shape.radius)**3. for b in O.bodies if isinstance(b.shape,Sphere)])
 v2=width*length*height
 Voidratio=(v2-v1)/v2*100.
 print'The Void Ratio:',Voidratio,'%','This is the second one'

     checker.command='checkUnbalancedtunnelmovement()'

def checkUnbalancedtunnelmovement():
 O.engines=O.engines+[TranslationEngine(translationAxis=[0,1,0],velocity=0.3,ids=TBM)]
 # start plotting the data now, it was not interesting before
    #O.engines=O.engines+[PyRunner(command='addPlotDataForceTunnel()',iterPeriod=200)]
 # we use it below to changefor s in O.bodies if isinstance(s.shape,Sphere):
 global CylinderforceX, CylinderforceY, CylinderforceZ
 O.engines=O.engines+[PyRunner(command='Changecolor()',iterPeriod=200)]

    CylinderforceX = utils.sumForces([10,14,16,22,26,30,34,36,42,46],(1,0,0))
 CylinderforceY = utils.sumForces([10,14,16,22,26,30,34,36,42,46],(0,1,0))
 CylinderforceZ = utils.sumForces([10,14,16,22,26,30,34,36,42,46],(0,0,1))

 Cylindernormalforce = sumFacetNormalForces([10,14,16,22,26,30,34,36,42,46],1)
 #print 'The sum of normal forces are: ',Cylindernormalforce

 plot.addData(CylinderforceX=CylinderforceX,tx=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),CylinderforceY=CylinderforceY,ty=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),CylinderforceZ=CylinderforceZ,tz=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),Cylindernormalforce=Cylindernormalforce,t=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),i=O.iter)
    # start plotting the data now, it was not interesting before
    #O.engines=O.engines+[PyRunner(command='addPlotDataForceTunnel()',iterPeriod=200)]
    # next time, do not call this function anymore, but the next one (unloadPlate) instead
    #O.pause()

#plot.saveDataTxt(O.tags['d.id']+'.txt')

def Changecolor():
   for s in O.bodies:
 s.shape.color=scalarOnColorScale(s.state.displ().norm(),0,2)
 #print 0.1*s.state.displ()
  # for changing color based on the movement of sheres. its attributes from the functions called
  #print 'Change'

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]-plate.state.refPos[2],unbalanced=unbalancedForce(),i=O.iter)

#Plotting the force on the tunnel face
def addPlotDataForceTunnel():
  print 'test => ',CylinderforceX
  plot.addData(CylinderforceX,tx=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),i=O.iter)

# besides unbalanced force evolution, also plot the displacement-force diagram
plot.plots={'tx':('CylinderforceX',),'ty':('CylinderforceY',),'tz':('CylinderforceZ',),'t':('Cylindernormalforce',)}
#plot.plots={'i':('unbalanced',),'w':('Fz',),'tx':('Facex',)}

plot.plot()

#O.saveTmp()
from yade import qt
v=qt.View()
v.eyePosition=(-1,0.3,0.25);v.upVector=(0,0,1); v.lookAt=(0,0,0); v.axes=False; v.sceneRadius=1.9

Revision history for this message
Clinton Schramm (clintonschramm) said :
#6

****Ammended Code

readParamsFromTable(rMean=.02,rRelFuzz=.003,maxLoad=1e5,minLoad=1e4)
# make rMean, rRelFuzz, maxLoad accessible directly as variables later
from yade.params.table import *
numspherespack1=1000
numspherespack2 = 173
Zextentbox = 0.200 #was .200
width = 0.154
length = 0.441
cylinderheight = 0.130
cylinderradius = 0.05
nosides = 10

#Set materials for spheres, and box
O.materials.append(FrictMat(young=78.71e6,poisson=0.27,frictionAngle=.5934,density=2600,label='spheres')) #Need to find youngs modulus
O.materials.append(FrictMat(young=30e9,poisson=0.2,frictionAngle=0,label='walls'))

# create box with free top, and ceate loose packing inside the box
from yade import pack, plot
O.bodies.append(geom.facetBox((0,0,0),(width/2,length/2,Zextentbox),wallMask=31,material='walls')) #(centre),(x,y,z) Old Box with correct dimensions
TBM=O.bodies.append(geom.facetCylinder(center=(-0.077,.1555,-.100),radius=cylinderradius,height=cylinderheight,orientation=Quaternion((1,0,0),3.1415926/2),segmentsNumber=nosides,wallMask=7,angleRange=None,closeGap=False,wire=False,highlight=False))

sp=pack.SpherePack()
sp.makeCloud((-0.077,0.180,-0.200),(0.077,-0.200,-0.155),rMean=rMean,rRelFuzz=rRelFuzz,num=numspherespack2) #Cloud for under tunnel
#May need to make cloud larger tos full up the model
sp.makeCloud((-0.077,0.180,-0.05),(0.077,-0.180,.55),rMean=rMean,rRelFuzz=rRelFuzz,num=numspherespack1) #Move cloud in +z 400
sp.toSimulation(material='spheres',color=(0,1,1))

O.engines=[
   ForceResetter(),
   # sphere, facet, wall
   InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb(),Bo1_Facet_Aabb(),Bo1_Wall_Aabb()]),
   InteractionLoop(
      # the loading plate is a wall, we need to handle sphere+sphere, sphere+facet, sphere+wall
      [Ig2_Sphere_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom(),Ig2_Wall_Sphere_ScGeom()],
      [Ip2_FrictMat_FrictMat_FrictPhys()],
      [Law2_ScGeom_FrictPhys_CundallStrack()]
   ),
   NewtonIntegrator(gravity=(0,0,-9.81),damping=0.5),
   SnapshotEngine(iterPeriod=300,fileBase='/home/clinton/Desktop/Video/1/Centri-',label='cent'),
   # the label creates an automatic variable referring to this engines
   PyRunner(command='checkUnbalanced1()',iterPeriod = 200,label='checker'),
   #PyRunner(command='Changecolor()',iterPeriod = 200),
]
O.dt=.5*PWaveTimeStep()

# the following checkUnbalanced, unloadPlate and stopUnloading functions are all called by the 'checker'
# (the last engine) one after another; this sequence defines progression of different stages of the
# simulation, as each of the functions, when the condition is satisfied, updates 'checker' to call
# the next function when it is run from within the simulation next time

# check whether the gravity deposition has already finished
# if so, add wall on the top of the packing and start the oedometric test
def checkUnbalanced1():
   # at the very start, unbalanced force can be low as there is only few contacts, but it does not mean the packing is stable
   if O.iter<5000: return
   # the rest will be run only if unbalanced is < .1 (stabilized packing)
   if unbalancedForce()>.1: return
   # add plate at the position on the top of the packing
   # the maximum finds the z-coordinate of the top of the topmost particle
   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,material='walls'))
   global plate # without this line, the plate variable would only exist inside this function
   plate=O.bodies[-1] # the last particles is the plate
   # Wall objects are "fixed" by default, i.e. not subject to forces
   # prescribing a velocity will therefore make it move at constant velocity (downwards)
   plate.state.vel=(0,0,-.7)
   # start plotting the data now, it was not interesting before
   #O.engines=O.engines+[PyRunner(command='addPlotData()',iterPeriod=200)]
   # next time, do not call this function anymore, but the next one (unloadPlate) instead
   checker.command='unloadPlate1()'

def unloadPlate1():
   # if the force on plate exceeds maximum load, start unloading
   if abs(O.forces.f(plate.id)[2])>maxLoad :
      plate.state.vel*=-3
      # next time, do not call this function anymore, but the next one (stopUnloading) instead
      checker.command='stopUnloading()'

def stopUnloading():

   if abs(O.forces.f(plate.id)[2])<minLoad:
 plate.state.vel*=0
 areacylinder = (.5*nosides*cylinderradius**2*(sin(degrees(360)/10)))/2
 Volcylinder = areacylinder*cylinderheight
        height = max([b.state.pos[2]+b.shape.radius for b in O.bodies if isinstance(b.shape,Sphere)])+Zextentbox
 print 'Height of heighest sphere is: ',height
 v1=Volcylinder+sum([4./3.*pi*(b.shape.radius)**3. for b in O.bodies if isinstance(b.shape,Sphere)])
 v2=width*length*height
 Voidratio=(v2-v1)/v2*100.
 print'The Void Ratio:',Voidratio,'%','This is the second one'

     checker.command='checkUnbalancedtunnelmovement()'

def checkUnbalancedtunnelmovement():
 O.engines=O.engines+[TranslationEngine(translationAxis=[0,1,0],velocity=0.3,ids=TBM)]
 # start plotting the data now, it was not interesting before
    #O.engines=O.engines+[PyRunner(command='addPlotDataForceTunnel()',iterPeriod=200)]
 # we use it below to changefor s in O.bodies if isinstance(s.shape,Sphere):
 global CylinderforceX, CylinderforceY, CylinderforceZ
 O.engines=O.engines+[PyRunner(command='Changecolor()',iterPeriod=200)]

    CylinderforceX = utils.sumForces([10,14,16,22,26,30,34,36,42,46],(1,0,0))
 CylinderforceY = utils.sumForces([10,14,16,22,26,30,34,36,42,46],(0,1,0))
 CylinderforceZ = utils.sumForces([10,14,16,22,26,30,34,36,42,46],(0,0,1))

 Cylindernormalforce = sumFacetNormalForces([10,14,16,22,26,30,34,36,42,46],1)
 #print 'The sum of normal forces are: ',Cylindernormalforce

 plot.addData(CylinderforceX=CylinderforceX,tx=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),CylinderforceY=CylinderforceY,ty=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),CylinderforceZ=CylinderforceZ,tz=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),Cylindernormalforce=Cylindernormalforce,t=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),i=O.iter)
    # start plotting the data now, it was not interesting before
    #O.engines=O.engines+[PyRunner(command='addPlotDataForceTunnel()',iterPeriod=200)]
    # next time, do not call this function anymore, but the next one (unloadPlate) instead
    #O.pause()

#plot.saveDataTxt(O.tags['d.id']+'.txt')

def Changecolor():
   for s in O.bodies:
 s.shape.color=scalarOnColorScale(s.state.displ().norm(),0,2)
 #print 0.1*s.state.displ()
  # for changing color based on the movement of sheres. its attributes from the functions called
  #print 'Change'

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]-plate.state.refPos[2],unbalanced=unbalancedForce(),i=O.iter)

#Plotting the force on the tunnel face
def addPlotDataForceTunnel():
  print 'test => ',CylinderforceX
  plot.addData(CylinderforceX,tx=(O.bodies[20].state.pos[1]-O.bodies[20].state.refPos[1]),i=O.iter)

# besides unbalanced force evolution, also plot the displacement-force diagram
plot.plots={'tx':('CylinderforceX',),'ty':('CylinderforceY',),'tz':('CylinderforceZ',),'t':('Cylindernormalforce',)}
#plot.plots={'i':('unbalanced',),'w':('Fz',),'tx':('Facex',)}

plot.plot()

#O.saveTmp()
from yade import qt
v=qt.View()
v.eyePosition=(-1,0.3,0.25);v.upVector=(0,0,1); v.lookAt=(0,0,0); v.axes=False; v.sceneRadius=1.9

Revision history for this message
Clinton Schramm (clintonschramm) said :
#7

Sorry for just spamming the code.

I'm not sure how else to explain it.

Cheers

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

Hi Clinton,

There could be several problems, why you don't see the spheres colored:
- the PyRynner is called not very often
- the scale is wrong (too small or too large)

follows your first example, for me works ok (particles goes from green to
yellow and to green again)
#########################################
readParamsFromTable(rMean=.05,rRelFuzz=.3,maxLoad=1e6,minLoad=1e4)
from yade.params.table import *

from yade import pack, plot
O.bodies.append(geom.facetBox((.5,.5,.5),(.5,.5,.5),wallMask=31))
sp=pack.SpherePack()
sp.makeCloud((0,0,0),(1,1,1),rMean=rMean,rRelFuzz=rRelFuzz)
sp.toSimulation()

O.engines=[
ForceResetter(),
InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb(),Bo1_Wall_Aabb()]),
InteractionLoop(
[Ig2_Sphere_Sphere_L3Geom(),Ig2_Facet_Sphere_L3Geom(),Ig2_Wall_Sphere_L3Geom()],
[Ip2_FrictMat_FrictMat_FrictPhys()],
[Law2_L3Geom_FrictPhys_ElPerfPl()]
),
NewtonIntegrator(gravity=(0,0,-9.81),damping=0.5),
PyRunner(command='checkUnbalanced()',realPeriod=2,label='checker'),
PyRunner(command='ccc()',iterPeriod=10,label='checker'),
]
O.dt=.5*PWaveTimeStep()
def checkUnbalanced():
print O.iter
if O.iter<5000: return
if unbalancedForce()>.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,-.1)
O.engines=O.engines+[PyRunner(command='addPlotData()',iterPeriod=200)]
checker.command='unloadPlate()'

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

def stopUnloading():
if abs(O.forces.f(plate.id)[2])<minLoad:
plot.saveDataTxt(O.tags['d.id']+'.txt')
O.pause()

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]-plate.state.refPos[2],unbalanced=unbalancedForce(),i=O.iter)

def ccc():
for s in O.bodies:
s.shape.color=scalarOnColorScale(s.state.displ().norm(),0,1)

O.run()
#########################################

cheers
Jan

PS: when posting a code, try to make it minimal - deleting functions, lines
and comments, that are not important (like plots)

2016-05-29 5:16 GMT+02:00 Clinton Schramm <
<email address hidden>>:

> Question #294531 on Yade changed:
> https://answers.launchpad.net/yade/+question/294531
>
> Clinton Schramm gave more information on the question:
> Sorry for just spamming the code.
>
> I'm not sure how else to explain it.
>
> Cheers
>
> --
> You received this question notification because your team yade-users 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
Jan Stránský (honzik) said :
#9

And if you need the color information not directly in simulation but for
postprocessing, another option is to export displacement information to vtk
files and use paraview for the postprocessing
cheers
Jan

2016-05-29 12:07 GMT+02:00 Jan Stránský <email address hidden>:

> Hi Clinton,
>
> There could be several problems, why you don't see the spheres colored:
> - the PyRynner is called not very often
> - the scale is wrong (too small or too large)
>
> follows your first example, for me works ok (particles goes from green to
> yellow and to green again)
> #########################################
> readParamsFromTable(rMean=.05,rRelFuzz=.3,maxLoad=1e6,minLoad=1e4)
> from yade.params.table import *
>
> from yade import pack, plot
> O.bodies.append(geom.facetBox((.5,.5,.5),(.5,.5,.5),wallMask=31))
> sp=pack.SpherePack()
> sp.makeCloud((0,0,0),(1,1,1),rMean=rMean,rRelFuzz=rRelFuzz)
> sp.toSimulation()
>
> O.engines=[
> ForceResetter(),
>
> InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb(),Bo1_Wall_Aabb()]),
> InteractionLoop(
>
> [Ig2_Sphere_Sphere_L3Geom(),Ig2_Facet_Sphere_L3Geom(),Ig2_Wall_Sphere_L3Geom()],
> [Ip2_FrictMat_FrictMat_FrictPhys()],
> [Law2_L3Geom_FrictPhys_ElPerfPl()]
> ),
> NewtonIntegrator(gravity=(0,0,-9.81),damping=0.5),
> PyRunner(command='checkUnbalanced()',realPeriod=2,label='checker'),
> PyRunner(command='ccc()',iterPeriod=10,label='checker'),
> ]
> O.dt=.5*PWaveTimeStep()
> def checkUnbalanced():
> print O.iter
> if O.iter<5000: return
> if unbalancedForce()>.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,-.1)
> O.engines=O.engines+[PyRunner(command='addPlotData()',iterPeriod=200)]
> checker.command='unloadPlate()'
>
> def unloadPlate():
> if abs(O.forces.f(plate.id)[2])>maxLoad:
> plate.state.vel*=-1
> checker.command='stopUnloading()'
>
> def stopUnloading():
> if abs(O.forces.f(plate.id)[2])<minLoad:
> plot.saveDataTxt(O.tags['d.id']+'.txt')
> O.pause()
>
> 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]-plate.state.refPos[2],unbalanced=unbalancedForce(),i=O.iter)
>
> def ccc():
> for s in O.bodies:
> s.shape.color=scalarOnColorScale(s.state.displ().norm(),0,1)
>
> O.run()
> #########################################
>
>
> cheers
> Jan
>
> PS: when posting a code, try to make it minimal - deleting functions,
> lines and comments, that are not important (like plots)
>
>
> 2016-05-29 5:16 GMT+02:00 Clinton Schramm <
> <email address hidden>>:
>
>> Question #294531 on Yade changed:
>> https://answers.launchpad.net/yade/+question/294531
>>
>> Clinton Schramm gave more information on the question:
>> Sorry for just spamming the code.
>>
>> I'm not sure how else to explain it.
>>
>> Cheers
>>
>> --
>> You received this question notification because your team yade-users 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
Clinton Schramm (clintonschramm) said :
#10

Thanks for all the tips Jan. I'll be sure to use them next time.

I've managed to get the colors changing, but the s.state.displ().norm() function seems to have a value even before that part of the code has been run (perhaps stored previosu displacements?

Is there a way to reset that value?

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

>
>
> I've managed to get the colors changing, but the s.state.displ().norm()
> function seems to have a value even before that part of the code has
> been run (perhaps stored previosu displacements?
>
> Is there a way to reset that value?

state.displ() is computed internally as state.pos - state.refPos, so the
displacement from the "original position".

state.refPos may be set manually to arbitrary value, you can try something
like b.state.refPos = b.state.pos. You can do this regularly to color the
particles according to "displacement increment" from previous color change.
This way is quite flexible, so depending on your needs you can use
different approaches.

cheers
Jan

Revision history for this message
Clinton Schramm (clintonschramm) said :
#12

Hi Jan

I have tried to implement what you said, but get the error "State object has no attribute 'Pos'

Could you give an example on how to reference this correctly. Ideally I would like to see the colour change based on the cummunulative displacement from a certain point. (When the translation engine begins)

def checkUnbalancedtunnelmovement():
   global voidcheck
   if voidcheck==2:
 O.engines=O.engines+[TranslationEngine(translationAxis=[0,1,0],velocity=0.05,ids=TBM)]
        for s in O.bodies:
      s.state.refPos[1]=s.state.Pos[1]
 O.engines=O.engines+[PyRunner(command='Changecolor()',iterPeriod=200)]
 print O.engines, '2'
 voidcheck=1
  # start plotting the data now, it was not interesting before
    #O.engines=O.engines+[PyRunner(command='addPlotDataForceTunnel()',iterPeriod=200)]
   checker.command='calculateforces()'

def Changecolor():
   for s in O.bodies:
  s.shape.color=scalarOnColorScale(s.state.displ().norm(),0,.7) # for changing color based on the movement of sheres.

Revision history for this message
Clinton Schramm (clintonschramm) said :
#13

Got it! Thanks so much for all your help Jan!