Running Woo

Command-line options

Woo is primarily a computation program, with only optional graphical user-interface. To run woo, type woo in the terminal (use wwoo under Windows). A number of options can be specified, given using UNIX convention of --long-option or -s (short option). A help on all available options is obtained with woo -h:

usage: woo [-h] [--version] [-j THREADS] [--cores CORES] [--cl-dev CLDEV] [-n]
           [-D] [--quirks QUIRKS] [--flavor FLAVOR] [-c COMMANDS] [-e EXPR]
           [--paused] [--nice NICE] [-x] [-v] [-R] [--test] [--no-gdb]
           [--in-gdb] [--in-pdb] [--in-valgrind]

Options important for everyday use are the following ones:

-j THREADS
Number of CPU cores to use for computation. Woo is parallelized using OpenMP, and runs on all cores by default. Depending on hardware and the nature of simulation, reasonable value is usually around -j4. Woo must have been compiled with the openmp feature for this option to have any effect.
-e
Evaluate given expression (should yield a Scene or a Preprocessor)
-n
Run without graphical interface.
-x
End once the simulation (or script) finishes.
--paused
When loading a simulation from the command line (below), don’t have it run immediately.
-R
Recompile Woo before running. Useful during development when sources are modified.
-RR
Update sources from the repository, recompile and run.

Woo takes an additional argument (existing file) coming after options. It can be

  1. *.py: python script which will be interpreted by Woo.
  2. Saved simulation (in any supported format), which will be loaded and run by Woo.
  3. Preprocessor, which will be run to create a new simulation, which will be run by Woo.

Once Woo starts, it shows an embedded command-prompt based on IPython. It can be used as general-purpose python console and to inspect and modify simulations:

../_images/woo-terminal1.png

To get started with scripting Woo, you should get familiar with Python, for instance using Python tutorial.

Import as python module

Woo can be used in python scripts. You only have to say import woo and everything should just work. Parameters which cannot be changed once woo is imported can be set via the wooMain.options object:

import wooMain
wooMain.options.ompThreads=4
wooMain.options.debug=True
import woo    # initializes OpenMP to 4 threads, and uses the debug build of woo

Graphical interface

Graphical interface is entirely optional in Woo, simulations can run without it (with the -n switch, when no $DISPLAY is available, in batch, or if compiled without the qt4 feature).

Controller

The main Woo window, called controller, is brought up automatically at startup if a simulation/script is given on the command-line (under Windows, the controller is always shown at startup). The controller can be manually brought up by pressing F12 in the terminal, or by typing woo.qt.Controller(). The window (when the first, Simulation tab, is active) looks like this:

../_images/controller-simulation.png

It is divided in several blocks –

  1. Time display (simulation time, clock time, step number, timestep)
  2. Loading/saving simulation, file where the simulation was last saved
  3. Running controls:
    • start/stop
    • advance by one timestep (or multiple steps, or substep)
    • reload from last saved file
  4. Display controls (toggle)
    • 3d (OpenGL) window
    • 2d plot window
    • Inspector
  5. Area for simulation-specific controls, if defined (woo.core.Scene.uiBuild)

The interface can display structured objects – for example, unde Controller ‣ Display we see something like this:

../_images/controller-display.png

Blue object/attribute labels are always active:

  • left-click opens online documentation for that particular class/attribute.
  • middle-click will copy path to that object to the clipboard, which can be then pasted into python.
  • each attribute has tooltip showing full documentation for that attribute; just hover over the label.
../_images/object-editor-tooltip1.png

For the object, attributes can be displayed either as variable names, or as their documentation, units can be enabled/disabled, and per-attribute checkboxes can be added for easy input-checking (when all values must be set):

../_images/object-editor-context-menu.png

3d rendering

Note

The 3d rendering part of Woo is described in detail in Integrated 3d view.

The 3d view is opened by clicking the “3D” button in the D part of the controller. It is navigated with mouse similar to other 3d software, and supports many keyboard shortcuts. It can be used to make movies by taking snapshots. Detailed settings are accessible in the Display tab of the controller. Details are given in dedicated section Integrated 3d view.

../_images/controller-3d.png

Preprocessor

Preprocessors can be set and run from the Preprocess tab, which can be opened directly from the terminal with F9 (Linux-only).

../_images/controller-preprocessor.png

In the top selection, all available preprocessors are listed. Preprocessor can be modified, loaded and saved. Once you have set all parameters, the play button bottom right will create new simulation and switch to the Simulation tab automatically.

Unit specifications are only representation. Technically is Woo unit-agnostic, practically, SI units are used everywhere. See woo._units for details.

The preprocessor can be saved for later use; it is saved, by default, as python expression. which is human-readable and easily editable:

##woo-expression##
#: import woo.pre.horse,woo.dem
woo.pre.horse.FallingHorse(
        radius=0.002,
        relGap=0.25,
        halfThick=0.002,
        relEkStop=0.02,
        damping=0.2,
        gravity=(0.0, 0.0, -9.81),
        pattern='hexa',
        mat=woo.dem.FrictMat(density=1000.0, id=-1, young=50000.0, tanPhi=0.5463024898437905, ktDivKn=0.2),
        meshMat=None,
        pWaveSafety=0.7,
        reportFmt='/tmp/{tid}.xhtml',
        vtkStep=40,
        vtkPrefix='/tmp/{tid}-'
)

Saving and loading things

Save

Simulation, or any piece of it, can be saved and loaded from/to file or memory buffer. For instance, a preprocessor object above might be saved in various ways:

horse=woo.pre.horse.FallingHorse()
horse.damping=0.4

horse.saveTmp()                           # save to the default memory buffer
horse.saveTmp('something')                # save to a named memory buffer
horse.dump('/tmp/somefile.json')          # save to file, guess format (JSON) to use from filename
horse.dump('/tmp/somefile.expr.gz')       # save to file, guess format (gzipped python expression) from filename
horse.dump('/tmp/somefile',format='json') # save to file, using the json format
dumpString=horse.dumps(format='expr')     # dump to a string variable

Objects can also be saved (and loaded) from the graphical user interface:

../_images/preprocessor-save.png

Load

Loading is more involved due to type hierarchy; after loading, the object is checked to be instance of whichever class’ method was called. File format is detected automatically when loading.

horse=woo.core.Object.load('/tmp/somefile.xml')            # FallingHorse is an Object, this is OK
horse=woo.pre.horse.FallingHorse.load('/tmp/somefile.xml') # FallingHorse is a FallingHorse, this is OK
horse=woo.dem.FrictMat.load('/tmp/somefile.xml')           # FallingHorse is not a FrictMat, raises exception
horse=woo.core.Object.loads(dumpString)                    # load from string variable
horse=woo.core.Object.loadTmp()                            # load from the default memory buffer
horse=woo.core.Object.loadTmp('something')                 # load from a named memory buffer

Formats

There is a number of format Woo can save into and load from.

Complete formats

are computer-readable formats designed to store as much useful information as possible, so that saved object can be loaded into identical state. They are rather efficient in terms of saving/loading speed.

Their principal limitation is that they are not compatible between different versions (or even builds) of Woo, since they rely on memory layout being identical.

Another limitation is that the c++/python boundary is not handled: python object deriving from a c++ object will only be saved as instance of the leaf class in c++; we attempt to detect this condition, but it should not be relied on.

Dump formats

store only some amount of information. Most of them are human-readable and human-modifiable, most of them are also computer-readable, but without the claim of reconstructing the entire object. They should be used form small objects (such as preprocessors, materials and so on), being less efficient than complete formats.

They are not guaranteed to be compatible between versions either, but they do remain compatible as long as the same attributes of a particular object are defined. They are also safe to use with c++ objects extended in python.

Note

File extension is only important when saving an object and format is not specified – auto-detection will be attempted based on file extension.

Extension is disregarded when loading an object, the format is always detected from the actual contents of the file.

The following table summarizes available formats:

Format Type Extension Description
binary complete -, .bin (compressed: .gz, .bz2)

Boost::serialization memory dump. This is the most efficient format in terms of speed. Compressed with gzip (by appending .gz) is quite storage-efficient.

This is the default format for saving entire simulations.

expr dump .expr

Text which is a valid python expression (with some special comments) evaluating to given object. It is extremely human-readable and human-writeable, thus recommended for small objects (preprocessors, in particular).

This is the default format for small objects, such as preprocessors.

Since special comments may contain any python commands, DO NOT load files unless you know what they contain (malicious user could e.g. instruct your computer to delete all files in your home directory).

XML complete .xml (compressed: .xml.gz .xml.bz2)

Boost::serialization dump written as XML. To some extent human-readable; efficient for speed, inefficient for storage. Best compressed with bzip2 (append .bz2).

Some builds may not support saving to XML, depending on compilation options.

JSON dump .json JavaScript Object Notation serves for excellent inter-language compatibility; this format is human- and computer-readable and writeable, but its syntax is limited. Use this format to load objects in Matlab, JavaScript and similar. Can store other objects than just instances of woo.core.Object.
pickle dump .pickle

Serialization format used extensively in the python world. It is only used internally by Woo, for some data stored in SQLite database, for instance.

Unlike most other formats, it can store other objects than those deriving from woo.core.Object and their sequences.

HTML dump .html Dump object to HTML table; this format is used when reports of simulation are generated (see e.g. Report). This format is write-only. It is the only format showing preferred unit for each quantity.

Format examples

To get a taste what those files look like, here are fragments of them.

Binary represented as hex dump:

00000000  16 00 00 00 00 00 00 00  73 65 72 69 61 6c 69 7a  |........serializ|
00000010  61 74 69 6f 6e 3a 3a 61  72 63 68 69 76 65 09 00  |ation::archive..|
00000020  04 08 04 08 01 00 00 00  00 01 00 00 00 02 00 05  |................|
00000030  00 00 00 00 00 00 00 53  63 65 6e 65 01 00 00 00  |.......Scene....|
00000040  00 00 00 00 00 01 00 00  00 00 01 00 00 00 3a 8c  |..............:.|
00000050  30 e2 8e 79 45 3e 00 00  00 00 00 00 00 00 00 ff  |0..yE>..........|
00000060  ff ff ff 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000070  00 00 00 00 00 00 00 00  00 00 ff ff ff ff ff ff  |................|
00000080  ff ff 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000090  00 00 f0 bf 00 00 00 00  00 00 f0 bf 00 00 00 00  |................|
000000a0  00 00 f0 bf 00 00 00 00  00 00 f0 3f 00 00 00 00  |...........?....|
000000b0  00 00 f0 3f 00 00 00 00  00 00 f0 3f 01 00 00 00  |...?.......?....|
000000c0  00 00 06 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000000d0  00 00 00 02 00 00 00 00  00 00 00 69 64 14 00 00  |...........id...|
000000e0  00 00 00 00 00 32 30 31  33 30 32 31 31 54 31 32  |.....20130211T12|
000000f0  32 30 30 31 70 39 34 32  38 03 00 00 00 00 00 00  |2001p9428.......|
00000100  00 69 64 74 14 00 00 00  00 00 00 00 32 30 31 33  |.idt........2013|
00000110  30 32 31 31 54 31 32 32  30 30 31 70 39 34 32 38  |0211T122001p9428|
00000120  07 00 00 00 00 00 00 00  69 73 6f 54 69 6d 65 0f  |........isoTime.|
00000130  00 00 00 00 00 00 00 32  30 31 33 30 32 31 31 54  |.......20130211T|
00000140  31 32 32 30 30 31 03 00  00 00 00 00 00 00 74 69  |122001........ti|
00000150  64 14 00 00 00 00 00 00  00 32 30 31 33 30 32 31  |d........2013021|
00000160  31 54 31 32 32 30 30 31  70 39 34 32 38 05 00 00  |1T122001p9428...|
00000170  00 00 00 00 00 74 69 74  6c 65 00 00 00 00 00 00  |.....title......|
00000180  00 00 04 00 00 00 00 00  00 00 75 73 65 72 0d 00  |..........user..|
00000190  00 00 00 00 00 00 65 75  64 6f 78 6f 73 40 66 6c  |......eudoxos@fl|
000001a0  61 69 72 00 00 00 00 00  00 00 00 00 00 00 00 00  |air.............|

XML includes attribute names and all data are stored in ASCII:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE boost_serialization>
<boost_serialization signature="serialization::archive" version="9">
<woo__Object class_id="0" tracking_level="0" version="1">
         <px class_id="2" class_name="Scene" tracking_level="1" version="0" object_id="_0">
                 <Object class_id="1" tracking_level="1" version="0" object_id="_1"></Object>
                 <dt>1e-08</dt>
                 <step>0</step>
                 <subStepping>0</subStepping>
                 <subStep>-1</subStep>
                 <time>0</time>
                 <stopAtStep>0</stopAtStep>
                 <isPeriodic>0</isPeriodic>
                 <trackEnergy>0</trackEnergy>
                 <clDev class_id="3" tracking_level="0" version="0">
                         <x>-1</x>
                         <y>-1</y>
                 </clDev>
                 <boxHint class_id="4" tracking_level="0" version="0">
                         <min class_id="5" tracking_level="0" version="0">
                                 <x>-1</x>
                                 <y>-1</y>
                                 <z>-1</z>
                         </min>
                         <max>
                                 <x>1</x>
                                 <y>1</y>
                                 <z>1</z>
                         </max>
                 </boxHint>

JSON is rather readable, but also quite verbose (note the special __class__ items, which are added so that reconstructing Woo objects is possible):

{
         "__class__": "woo.pre.horse.FallingHorse",
         "damping": 0.2,
         "gravity": [
                 0.0,
                 0.0,
                 -9.81
         ],
         "halfThick": 0.002,
         "mat": {
                 "__class__": "woo.dem.FrictMat",
                 "density": 1000.0,
                 "id": -1,
                 "ktDivKn": 0.2,
                 "tanPhi": 0.5463024898437905,
                 "young": 50000.0
         },
         "meshMat": null,
         "pWaveSafety": 0.7,
         "pattern": "hexa",
         "radius": 0.002,
         "relEkStop": 0.02,
         "relGap": 0.25,
         "reportFmt": "/tmp/{tid}.xhtml",
         "vtkPrefix": "/tmp/{tid}-",
         "vtkStep": 40
}

Python expression format is trivial to read, modify and write by human; indentation is not important, the #: sequence introduces commands which will be executed before evaluating the expression (usually import statements):

##woo-expression##
#: import woo.pre.horse,woo.dem
woo.pre.horse.FallingHorse(
        radius=0.002,
        relGap=0.25,
        halfThick=0.002,
        relEkStop=0.02,
        damping=0.2,
        gravity=(0.0, 0.0, -9.81),
        pattern='hexa',
        mat=woo.dem.FrictMat(density=1000.0, id=-1, young=50000.0, tanPhi=0.5463024898437905, ktDivKn=0.2),
        meshMat=None,
        pWaveSafety=0.7,
        reportFmt='/tmp/{tid}.xhtml',
        vtkStep=40,
        vtkPrefix='/tmp/{tid}-'
)

Python’s pickle format (the ASCII-based one):

cwoo.pre.horse
FallingHorse
p0
(tRp1
  (dp2
S'mat'
p3
cwoo.dem
FrictMat
p4
(tRp5
(dp6
S'id'
p7
I-1
sS'ktDivKn'
p8
F0.2
sS'tanPhi'
p9
F0.5463024898437905
…

HTML dump is a XHTML-fragment (optionally with head and body tags as shown here):

<head>
        <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
</head>
<body>
        <table cellpadding="2px" rules="all" frame="box">
                <th colspan="3" align="left"><b>pre.horse.FallingHorse</b></th>
                <tr>
                        <td colspan="3"><i>&#9656; General</i></td>
                </tr>
                <tr>
                        <td>radius</td>
                        <td align="right">2</td>
                        <td align="right">mm</td>
                </tr>
                <tr>
                        <td>relGap</td>
                        <td align="right">0.25</td>
                        <td align="right">&#8722;</td>
                </tr>
                <tr>
                        <td>halfThick</td>
                        <td align="right">2</td>
                        <td align="right">mm</td>
                </tr>
                <tr>
                        <td>relEkStop</td>
                        <td align="right">0.02</td>
                        <td align="right">&#8722;</td>
                </tr>

Tip

Got questions? Ask at ask.woodem.org. Report issues to github.