Why is my pyrunner command not being called?

Asked by Xifan Li

I want to use pyrunner's command to control the loading and unloading process, but it doesn't work.

So I was wondering maybe there's something wrong with the engine code, so I add the "print ('hello')", and it did work. But the pyrunner command still doesn't work. I do not know what is going wrong.

Here is my code, could you please help me to check about it?

Many thanks for your help.

##########################
from yade import pack
# The following 5 lines will be used later for batch execution
nRead=readParamsFromTable(
 num_spheres=1000,# 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

num_spheres=table.num_spheres# number of spheres
key=table.key
targetPorosity = 0.43 #the porosity we want for the packing
compFricDegree = table.compFricDegree # initial contact friction during the confining phase (will be decreased during the REFD compaction process)
finalFricDegree = 30 # contact friction during the deviatoric loading
rate=-0.02 # loading rate (strain rate)
damp=0.2 # damping coefficient
stabilityThreshold=0.01 # we test unbalancedForce against this value in different loops (see below)
young=5e6 # contact stiffness
mn,mx=Vector3(0,0,0),Vector3(10,10,.1) # corners of the initial packing

## create materials for spheres and plates
O.materials.append(FrictMat(young=young,poisson=0.5,frictionAngle=radians(compFricDegree),density=2600,label='spheres'))
O.materials.append(FrictMat(young=young,poisson=0.5,frictionAngle=0,density=0,label='walls'))

## create walls around the packing
walls=aabbWalls([mn,mx],thickness=0,material='walls')
wallIds=O.bodies.append(walls)

## use a SpherePack object to generate a random loose particles packing
sp=pack.SpherePack()

sp.makeCloud(minCorner=mn,maxCorner=mx,rRelFuzz=0,num=2000)
sp.toSimulation(material='spheres')

triax=TriaxialStressController(

 maxMultiplier=1.+2e4/young, # spheres growing factor (fast growth)
 finalMaxMultiplier=1.+2e3/young, # spheres growing factor (slow growth)
 thickness = 0,

 internalCompaction=False,

 stressMask = 1,
        goal1=-2e5,
 goal2=rate,

 )

O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb()]),
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom()],
  [Ip2_FrictMat_FrictMat_FrictPhys()],
  [Law2_ScGeom_FrictPhys_CundallStrack()]
 ),
 GlobalStiffnessTimeStepper(active=1,timeStepUpdateInterval=100,timestepSafetyCoefficient=0.8),

 triax,

 TriaxialStateRecorder(iterPeriod=100, file='WallStresses.txt'),
 NewtonIntegrator(damping=damp),
 PyRunner(command='triaxload()',iterPeriod=1, label='triaxload'),
]

triax.stressMask = 1
triax.goal1=-2e5
triax.goal2=rate

print('hello')

def triaxload():

 if abs(O.triax.stress(triax.wall_top_id)[1])> 150000:
  triax.stressMask = 1
  triax.goal1=-3e5
  triax.goal2=rate
  triaxload.command=('triaxunload')

def triaxunload():
 if abs(triax.stress(triax.wall_top_id)[1])< 5e4:
  triax.stressMask = 1
  triax.goal1=-1e5
  triax.goal2=rate

from yade import plot

O.engines=O.engines[0:5]+[PyRunner(iterPeriod=20,command='history()',label='recorder')]+O.engines[5:7]
def history():
 plot.addData(e11=-triax.strain[0],
         e22=-triax.strain[1],
  s11=-triax.stress(triax.wall_right_id)[0],
  s22=-triax.stress(triax.wall_top_id)[1],

  i=O.iter)

plot.plots={'e11': ('s11',),'e22': ('s22',)}

O.saveTmp()
plot.plot()

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Xifan Li
Solved:
Last query:
Last reply:
Revision history for this message
Robert Caulk (rcaulk) said :
#1

Hello,

Your PyRunner is calling 'triaxunload()'. Your print statement is not inside triaxunload(), thus it will not be called.

Cheers,

Robert

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

Hello,

> but it doesn't work.

please be more specific. Is there any error? It has / seems to have no effect? ... ?
Also, try to provide a MWE [1]. I.e., if your problem is PyRunner, use just one PyRunner and try to localize the problem.

> So I was wondering maybe there's something wrong with the engine code, so I add the "print ('hello')"

why did not you put it inside the PyRunner, but to the topmost code?

> and it did work. But the pyrunner command still doesn't work. I do not know what is going wrong.

put the print inside PyRunner function, together with more valuable info then "hello", (e.g. O.iter etc.)
PyRunner is called at the intervals you provide and does what you tell it to do.

> triaxload.command=('triaxunload')

('triaxunload') does nothing. Next time the PyRunner calls what you provide, i.e. triaxunload, which is just name of a function. It does not call it.
What about
triaxload.command='triaxunload()'
?

> O.engines=O.engines[0:5]+[...]+O.engines[5:7]

this code is very likely to produce errors. E.g. if you add an engine and leave indices 5 and 7, it does completely different thing than you want.
It has some use cases, like setting engines, do running, change engines.
But since you do this before any running, put the "additional" engines directly to O.engines = [...] code.

Cheers
Jan

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

Revision history for this message
Xifan Li (shelvan) said :
#3

Thank you Robert,

But the point is not the print function, I mean that the above code can run the print() command, but cannot run the triaxload() and triaxunload() command.

I add the print() command in order to confirm that my code can run normally, but my main objective is to run the triaxload() & triaxunload() command during the simulation.

Revision history for this message
Xifan Li (shelvan) said :
#4

Thank you all guys. I just fixed the problem. I called the pyrunner command succesfully!

I realize that if we want to use the existing engine (like TriaxStressController, TriaxCompressionEngine) to call the pyrunner command to change the simulation proceed. We cannot simply add the pyrunner in the O.engines, we have to add the pyrunner command in this line:
O.engines=O.engines[0:5]+[...]+O.engines[5:7]

in the middle between O.engines[0:5] and O.engines[5:7], after adding the pyrunner command, so we can def the command as we want in the following part.

Many thanks to Jan who gave me the inspiration and Rober as well and other people who take their time to look at my problem.

Cheers

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

> I just fixed the problem. I called the pyrunner command succesfully!

For future reference (if somebody goes here looking for solution of the same / similar problem), could you please specify how you fixed the problem?
The working code would probably do the job.

> We cannot simply add the pyrunner in the O.engines, we have to add the pyrunner command in this line:
> O.engines=O.engines[0:5]+[...]+O.engines[5:7]
>
> in the middle between O.engines[0:5] and O.engines[5:7], after adding the pyrunner command, so we can def the command as we want in the following part.

Sorry, but this is (or at least should not) be true.
You do NOT have to add anything the way
O.engines=O.engines[0:5]+[...]+O.engines[5:7]
Contrary, I strongly discourage this approach (explained in earlier answers).
Moreover, O.engines=O.engines[0:5]+[...]+O.engines[5:7] essentially is equivalent to "simply add the pyrunner in the O.engines".

Cheers
Jan

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

See https://yade-dem.org/doc/user.html#base-engines "The O.engines sequence must be always assigned at once [..]" end part