Directory tree is hierarchical way to organize files in operating systems. A typical (reduced) tree looks like this:
/ Root
├──boot System startup
├──bin Low-level programs
├──lib Low-level libraries
├──dev Hardware access
├──sbin Administration programs
├──proc System information
├──var Files modified by system services
├──root Root (administrator) home directory
├──etc Configuration files
├──media External drives
├──tmp Temporary files
├──usr Everything for normal operation (usr = UNIX system resources)
│ ├──bin User programs
│ ├──sbin Administration programs
│ ├──include Header files for c/c++
│ ├──lib Libraries
│ ├──local Locally installed software
│ └──doc Documentation
└──home Contains the user's home directories
├──user Home directory for user
└──user1 Home directory for user1
Note that there is a single root /; all other disks (such as USB sticks) attach to some point in the tree (e.g. in /media).
If yade is installed on the machine, it can be (roughly speaking) run as any other program; without any arguments, it runs in the “dialog mode”, where a command-line is presented:
user@machine:~$ yade
Welcome to Yade bzr2616
TCP python prompt on localhost:9002, auth cookie `adcusk'
XMLRPC info provider on http://localhost:21002
[[ ^L clears screen, ^U kills line. F12 controller, F11 3d view, F10 both, F9 generator, F8 plot. ]]
Yade [1]: #### hit ^D to exit
Do you really want to exit ([y]/n)?
Yade: normal exit.
The command-line is in fact python, enriched with some yade-specific features. (Pure python interpreter can be run with python or ipython commands).
Instead of typing commands on-by-one on the command line, they can be be written in a file (with the .py extension) and given as argument to Yade:
user@machine:~$ yade simulation.py
For a complete help, see man yade
Exercises
We assume the reader is familar with Python tutorial and only briefly review some of the basic capabilities. The following will run in pure-python interpreter (python or ipython), but also inside Yade, which is a super-set of Python.
Numerical operations and modules:
Variables:
Lists are variable-length sequences, which can be modified; they are written with braces [...], and their elements are accessed with numerical indices:
Lists can be created in various ways:
List of squares of even number smaller than 20, i.e. (note the similarity):
Tuples are constant sequences:
Mapping from keys to values:
Exercises
Read the following code and say what wil be the values of a and b:
a=range(5)
b=[(aa**2 if aa%2==0 else -aa**2) for aa in a]
Yade objects are constructed in the following manner (this process is also called “instantiation”, since we create concrete instances of abstract classes: one individual sphere is an instance of the abstract Sphere, like Socrates is an instance of “man”):
Particles are the “data” component of simulation; they are the objects that will undergo some processes, though do not define those processes yet.
There is a number of pre-defined functions to create particles of certain type; in order to create a sphere, one has to (see the source of utils.sphere for instance):
In order to avoid such tasks, shorthand functions are defined in the utils module; to mention a few of them, they are utils.sphere, utils.facet, utils.wall.
In the last example, the particle was fixed in space by the fixed=True parameter to utils.sphere; such a particle will not move, creating a primitive boundary condition.
A particle object is not yet part of the simulation; in order to do so, a special function is called:
There are functions to generate a specific arrangement of particles in the pack module; for instance, cloud (random loose packing) of spheres can be generated with the pack.SpherePack class:
Note
Vector3 is class representing 3D vector; a number of geometry operations are supported by Vector3, such as scalar product, dot product, cross product, norm, addition and more. There are other similar classes such as Vector2, Matrix3 (3×3 matrix), Quaterion, Vector6 etc. See miniEigen module documentation for details.
utils.facet (triangle Facet) and utils.wall (infinite axes-aligned plane Wall) geometries are typically used to define boundaries. For instance, a “floor” for the simulation can be created like this:
There are other conveinence functions (like utils.facetBox for creating closed or open rectangular box, or family of ymport functions)
The simulation can be inspected in several ways. All data can be accessed from python directly:
Besides that, Yade says this at startup (the line preceding the command-line):
[[ ^L clears screen, ^U kills line. F12 controller, F11 3d view, F10 both, F9 generator, F8 plot. ]]
Exercises
Engines define processes undertaken by particles. As we know from the theoretical introduction, the sequence of engines is called simulation loop. Let us define a simple interaction loop:
Instead of typing everything into the command-line, one can describe simulation in a file (script) and then run yade with that file as an argument. We will therefore no longer show the command-line unless necessary; instead, only the script part will be shown. Like this:
O.engines=[ # newlines and indentations are not important until the brace is closed
ForceResetter(),
InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Wall_Aabb()]),
InteractionLoop( # dtto for the parenthesis here
[Ig2_Sphere_Sphere_L3Geom_Inc(),Ig2_Wall_Sphere_L3Geom_Inc()],
[Ip2_FrictMat_FrictMat_FrictPhys()],
[Law2_L3Geom_FrictPhys_ElPerfPl()]
),
GravityEngine(gravity=(0,0,-9.81)), # 9.81 is the gravity acceleration, and we say that
NewtonIntegrator(damping=.2,label='newton') # define a name under which we can access this engine easily
]
Besides engines being run, it is likewise important to define how often they will run. Some engines can run only sometimes (we will see this later), while most of them will run always; the time between two successive runs of engines is timestep (). There is a mathematical limit on the timestep value, called critical timestep, which is computed from properties of particles. Since there is a function for that, we can just set timestep using utils.PWaveTimeStep:
O.dt=utils.PWaveTimeStep()
Each time when the simulation loop finishes, time O.time is advanced by the timestep O.dt:
For experimenting with a single simulations, it is handy to save it to memory; this can be achieved, once everything is defined, with:
O.saveTmp()
Exercises
See also
The Bouncing sphere example shows a basic simulation.