'Name error' while calling function

Asked by subha

Hi All,

I am simulating a particle impact on a flat surface and would like to track the position and kinetic energy of the particle.
I am using yade 1.07 version on Ubuntu 14.04 LTS.

I encountered a problem with the "PyRunner" in my script while executing a function meant for saving data after every N iteration.

The script is given below:

from yade import qt
from yade import plot,pack,geom

#define material properties:

rho = 2500 #density
fric = 0.5 #friction coefficient
fric_angle = atan(fric) #friction angle in radian
stiff_n = 1e8
stiff_s = 1e8
c_n = 0.1 #normal viscous damping
c_s = 0.1 #shear viscous damping
l_d = 0.2 #local damping

#define a material:

Mat = O.materials.append(ViscElMat(kn=stiff_n, ks=stiff_s, \
cn=c_n, cs=c_s, density=rho, frictionAngle=fric_angle))

#create a sphere:

b1 = utils.sphere(center=(0,0.0,1),radius=0.05,fixed=False,material=Mat)
O.bodies.append(b1)

#O.bodies.append(utils.sphere(center=(0,0,1), radius=0.05, material=Mat))

#create a plane facet:

O.bodies.append(geom.facetBox(center=(0,0,0), extents=(0.5,0.5,0), fixed=True, material=MyMaterial))

#define engines:

O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]), #Axis-aligned bounding box
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom6D(),Ig2_Facet_Sphere_ScGeom()], #Interaction geometry
  [Ip2_ViscElMat_ViscElMat_ViscElPhys()], #Interaction physics
  [Law2_ScGeom_ViscElPhys_Basic()], #Contact law
 ),
 GravityEngine(gravity=(0,0,-9.81)),
 NewtonIntegrator(damping=l_d),

 qt.SnapshotEngine(fileBase='/home/subhasish/YADE/tutorials/image/',label='snapper',iterPeriod=100),
 PyRunner(iterPeriod=5,command='plotAddData()')
]

O.run(50000)

#show geometry:

v=qt.View(); v.axes=True
v.viewDir=Vector3(0,1,-.05)
v.eyePosition=Vector3(0,-5,.5)

O.dt = 1e-4

#O.dt=.5*utils.PWaveTimeStep()

def plotAddData():
 pos = b1.state.pos
 Intrs = len( b1.intrs())
 plot.addData(i=O.iter,t=O.time,x=pos[0], y=pos[1], z=pos[2], Ek=utils.kineticEnergy(), nIntrs=nIntrs)
 plot.saveDataTxt('file2.txt.bz2')

The error appeared on the terminal as "NameError: name 'plotAddDatan' is not defined". I came across similar problem in this forum but none seems to work. Any help would be appreciated.

Regards,

Subha

Question information

Language:
English Edit question
Status:
Solved
For:
Yade Edit question
Assignee:
No assignee Edit question
Solved by:
Klaus Thoeni
Solved:
Last query:
Last reply:
Revision history for this message
Klaus Thoeni (klaus.thoeni) said :
#1

Hi, simply move the definition "def plotAddData():" before your engines. The function needs to be defined before calling it.

HTH
Klaus

Revision history for this message
subha (subhasish-mitra) said :
#2

Hi Klaus,

Thanks for a prompt reply. I moved the function definition block before the engine declaration block as per your suggestion and executed the code.

The problem however still persists. The error message appearing on the terminal is as follows:

NameError Traceback (most recent call last)
/usr/bin/yade in <module>()

NameError: name 'plotAddData' is not defined

Any other suggestion?

Subha

Revision history for this message
Klaus Thoeni (klaus.thoeni) said :
#3

Hi,

I didn't run the script previously but when looking at it in more detail now I can see there are a couple of issues. Below is a running version.

HTH
K

from yade import qt
from yade import plot,pack,geom

#define material properties:

rho = 2500 #density
fric = 0.5 #friction coefficient
fric_angle = atan(fric) #friction angle in radian
stiff_n = 1e8
stiff_s = 1e8
c_n = 0.1 #normal viscous damping
c_s = 0.1 #shear viscous damping
l_d = 0.2 #local damping

#define a material:

Mat = O.materials.append(ViscElMat(kn=stiff_n, ks=stiff_s, \
cn=c_n, cs=c_s, density=rho, frictionAngle=fric_angle))

#create a sphere:

b1 = utils.sphere(center=(0,0.0,1),radius=0.05,fixed=False,material=Mat)
O.bodies.append(b1)

#O.bodies.append(utils.sphere(center=(0,0,1), radius=0.05, material=Mat))

#create a plane facet:

O.bodies.append(geom.facetBox(center=(0,0,0), extents=(0.5,0.5,0), fixed=True, material=Mat))

# define data collector
def plotAddData():
 pos = b1.state.pos
 nIntrs = len( b1.intrs())
 plot.addData(i=O.iter,t=O.time,x=pos[0], y=pos[1], z=pos[2], Ek=utils.kineticEnergy(), nIntrs=nIntrs)

#define engines:

O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]), #Axis-aligned bounding box
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom6D(),Ig2_Facet_Sphere_ScGeom()], #Interaction geometry
  [Ip2_ViscElMat_ViscElMat_ViscElPhys()], #Interaction physics
  [Law2_ScGeom_ViscElPhys_Basic()], #Contact law
 ),
 NewtonIntegrator(gravity=(0,0,-9.81),damping=l_d),

# qt.SnapshotEngine(fileBase='/home/subhasish/YADE/tutorials/image/',label='snapper',iterPeriod=100),
 PyRunner(iterPeriod=5,command='plotAddData()')
]

#show geometry:

v=qt.View(); v.axes=True
v.viewDir=Vector3(0,1,-.05)
v.eyePosition=Vector3(0,-5,.5)

O.dt = 1e-4

#O.dt=.5*utils.PWaveTimeStep()

# wait=True will cause not returning to python until simulation will have stopped
O.run(50000,True)

# run this outside pyRunner for performance
plot.saveDataTxt('file2.txt.bz2')

Revision history for this message
subha (subhasish-mitra) said :
#4

Hi Klaus,

Thanks again to have a look at this. Sadly, the problem still persists. The outcome is:

ameError Traceback (most recent call last)
/usr/bin/yade in <module>()

NameError: name 'plotAddData' is not defined

and no data were written in the "txt" file.

I copy-pasted the modified code as it is and executed using both "yade" (ver. 1.07) and "yadedaily" (ver. 1.20) through the command execfile('filename.py').

Since you checked the code running at your end, I'm thinking about any missing "yade" component during installation. What would be your thought on this?

Many thanks.

Subha

Revision history for this message
Best Klaus Thoeni (klaus.thoeni) said :
#5

Hi,

the script is working for me and I can't see why it shouldn't work.

You should execute the script in the terminal as follows:

yade script.py
OR
yadedaily script.py

Klaus

Revision history for this message
subha (subhasish-mitra) said :
#6

Thanks Klaus!

It worked when executed with yade "filename.py".

Just wondering what is the difference when the script is run using execfile("filename.py") and yade "filename.py" because the former one works fine when no function is added.

Just another comment, I wanted to save both snapshots and data at the same time using PyRunner and for that purpose, I added the following lines to the script:

O.engines+=[PyRunner(iterPeriod=100,command='saveImg()'),
 PyRunner(iterPeriod=5,command='plotAddData()')]

and defined the image saving function as:

def saveImg():
 qt.SnapshotEngine(fileBase='/home/subhasish/YADE/tutorials/image/img-')

The geometry is shown in runtime as before:

#show geometry:

v=qt.View(); v.axes=True
v.viewDir=Vector3(0,1,-.05)
v.eyePosition=Vector3(0,-5,.5)

The script, however, does not save any runtime image.

Any suggestion will be appreciated.

Regards,

Subha

Revision history for this message
subha (subhasish-mitra) said :
#7

Thanks Klaus Thoeni, that solved my question.

Revision history for this message
Klaus Thoeni (klaus.thoeni) said :
#8

Hi,

by using execfile not all yade modules are imported correctly.

Regarding your SnapshotEngine, just use it the way you had it before and make sure the directory you want to write into exists.

O.engines=[
 ForceResetter(),
 InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]), #Axis-aligned bounding box
 InteractionLoop(
  [Ig2_Sphere_Sphere_ScGeom6D(),Ig2_Facet_Sphere_ScGeom()], #Interaction geometry
  [Ip2_ViscElMat_ViscElMat_ViscElPhys()], #Interaction physics
  [Law2_ScGeom_ViscElPhys_Basic()], #Contact law
 ),
 NewtonIntegrator(gravity=(0,0,-9.81),damping=l_d),
 qt.SnapshotEngine(fileBase='your-sub-directory/img-',label='snapper',iterPeriod=100), # set directory
 PyRunner(iterPeriod=5,command='plotAddData()')
]

In addition, you have to set wait=False when you run it:

O.run(50000,False)

or just use the controller/python interface to run the simulation.

K

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

Regarding #6, I think your problem arose from variable scope (global or local) -- rather than modules issues.

Python variables / functions may have different scope (leading to possibility or impossibility to access them) depending how you launch your python script.

I bet that your python "plotAddData" function had a local scope when using execfile(...), as opposed to a global one when using yade yourScript.py

There has been previous (more precise) discussion on such topic in the mailing list before, but I can not tell you where/when...

Revision history for this message
subha (subhasish-mitra) said :
#10

Hi Klaus,

I noticed that if O.run(N,False) is used, the script does not write the data in the text file, but saves the images.

SM

Revision history for this message
subha (subhasish-mitra) said :
#11

Hi Jerome,

Thanks for your comment. How do I define the scope of a function local or global in the script?

Thanks,

SM

Revision history for this message
Klaus Thoeni (klaus.thoeni) said :
#12

add #10: you have two options:
1. execute the line plot.saveDataTxt('file2.txt.bz2') in the terminal after you have finished the simulation
2. put the line back where you had it at the beginning, it was only a suggestion to move it outside the PyRunner for better performance

K

Revision history for this message
subha (subhasish-mitra) said :
#13

Thanks Klaus,

For some reason, option#1 resulted in a segmentation fault (core dumped) however option#2 worked but obviously at the expense of increased simulation time as you previously indicated.

SM

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

As for # 11, I finally found the previous discussion I had in mind. See https://answers.launchpad.net/yade/+question/239546, which should tell you how to directly define variables / functions scope.

Revision history for this message
subha (subhasish-mitra) said :
#15

Thanks Jerome. That post was very helpful indeed.