← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-pkg/yade/git-trunk] Rev 3367: Merge branch 'master' of https://github.com/yade/trunk into chaoUnsat

 

Merge authors:
  Alexander Eulitz [Eugen] (kubeu)
  Anton Gladky (gladky-anton)
  Anton Gladky (gladky-anton)
  Bruno Chareyre (bruno-chareyre)
  christian <christian@localhost.localdomain>...

------------------------------------------------------------
revno: 3367 [merge]
committer: Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>
timestamp: Wed 2013-05-15 18:37:49 +0200
message:
  Merge branch 'master' of https://github.com/yade/trunk into chaoUnsat
  
  Conflicts:
  	pkg/dem/FlowEngine.hpp
removed:
  cMake/FindEigen2.cmake
  doc/sphinx/external.rst
  examples/concrete/cpm-dem3dof-scgeom.py
  examples/concrete/dem3dof-scgeom.table
  examples/test/peri8.py
  extra/boost_python_len.hpp
  extra/foreach.hpp_local
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/algorithms.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_proxy.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_suite.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_traits.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/deque.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/element_proxy.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/element_proxy_traits.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/int_slice_helper.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/iterator_range.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/iterator_traits.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/list.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/map.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/methods.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/multimap.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/pair.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/proxy_iterator.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/python_iterator.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/set.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/shared_proxy_impl.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/slice.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/slice_handler.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/suite_utils.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/value_traits.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/vector.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/visitor.hpp
  py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/workaround.hpp
  py/manpage.py
  scripts/debian/
  scripts/debian-packages
  scripts/debian-prep
  scripts/debian/compat
  scripts/debian/control-template
  scripts/debian/copyright
  scripts/debian/rules
  scripts/debian/source/
  scripts/debian/source/format
  scripts/debian/watch
  scripts/debian/yade-doc.doc-base-template
  scripts/debian/yade-doc.docs-template
  scripts/debian/yade.desktop-template
  scripts/debian/yade.docs-template
  scripts/debian/yade.examples-template
  scripts/debian/yade.install-template
  scripts/debian/yade.menu-template
  scripts/debian/yade.postinst-template
  scripts/debian/yade16x16.xpm
  scripts/debian/yade32x32.xpm
  site_scons/
  site_scons/site_tools/
  site_scons/site_tools/qt4/
  site_scons/site_tools/qt4/__init__.py
added:
  cMake/FindLoki.cmake
  cMake/FindNumPy.cmake
  cMake/FindPythonModule.cmake
  cMake/GNUInstallDirs.cmake
  doc/sphinx/ipython_directive013.py
  examples/clumps/adaptClumpMasses-example.py
  examples/clumps/addToClump-example.py
  examples/clumps/releaseFromClump-example.py
  examples/clumps/replaceByClumps-example.py
  examples/simple-scene/simple-scene-default-engines.py
  examples/test/combined-kinematic-engine.py
  pkg/dem/InelastCohFrictMat.cpp
  pkg/dem/InelastCohFrictMat.hpp
  pkg/dem/InelastCohFrictPhys.cpp
  pkg/dem/InelastCohFrictPhys.hpp
  pkg/dem/Ip2_2xInelastCohFrictMat_InelastCohFrictPhys.cpp
  pkg/dem/Ip2_2xInelastCohFrictMat_InelastCohFrictPhys.hpp
  pkg/dem/Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment.cpp
  pkg/dem/Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment.hpp
modified:
  CMakeLists.txt
  README.rst
  core/Body.cpp
  core/BodyContainer.cpp
  core/BodyContainer.hpp
  core/Cell.cpp
  core/Cell.hpp
  core/Clump.cpp
  core/Clump.hpp
  core/EnergyTracker.hpp
  core/Engine.hpp
  core/Functor.hpp
  core/InteractionContainer.cpp
  core/Scene.cpp
  core/State.hpp
  core/main/main.py.in
  core/main/yade-batch.in
  doc/sphinx/conf.py
  doc/sphinx/fig/dispatch-loop.svg
  doc/sphinx/formulation.rst
  doc/sphinx/index-toctree.rst
  doc/sphinx/installation.rst
  doc/sphinx/introduction.rst
  doc/sphinx/prog.rst
  doc/sphinx/templates/index.html
  doc/sphinx/tutorial-data-mining.rst
  doc/sphinx/tutorial-hands-on.rst
  doc/sphinx/tutorial/06-periodic-triaxial-test.py
  doc/sphinx/user.rst
  doc/sphinx/yadeSphinx.py
  doc/yade-articles.bib
  doc/yade-conferences.bib
  doc/yade-theses.bib
  examples/CapillaryPhys-example.py
  examples/ResetRandomPosition.py
  examples/baraban/baraban.py
  examples/baraban/rotating-cylinder.py
  examples/bulldozer/README
  examples/bulldozer/bulldozer.py
  examples/bulldozer/bulldozerVTK.py
  examples/chained-cylinders/CohesiveCylinderSphere.py
  examples/chained-cylinders/chained-cylinder-roots.py
  examples/chained-cylinders/chained-cylinder-spring.py
  examples/clumps/clump-hopper-viscoelastic.py
  examples/clumps/clump-inbox-viscoelastic.py
  examples/clumps/clump-viscoelastic.py
  examples/clumps/triax-basic-with-clumps.py
  examples/concrete/README
  examples/concrete/interaction-histogram.py
  examples/concrete/periodic.py
  examples/concrete/uniax.py
  examples/funnel.py
  examples/grids/Simple_Grid_Falling.py
  examples/gts-horse/gts-horse.py
  examples/hdaps.py
  examples/mill.py
  examples/normalInelasticity-test.py
  examples/not-working/Se3Interpolator.py
  examples/not-working/facet-topo.py
  examples/not-working/insertion-sort-collider.py
  examples/not-working/triax-identical-results.py
  examples/packs/packs.py
  examples/periodic-compress.py
  examples/periodic-grow.py
  examples/periodicSandPile.py
  examples/ring2d/ringCundallDamping.py
  examples/ring2d/ringSimpleViscoelastic.py
  examples/rod-penetration/model.py
  examples/simple-scene/simple-scene-energy-tracking.py
  examples/simple-scene/simple-scene-plot.py
  examples/simple-scene/simple-scene.py
  examples/simple-shear/simpleShear.py
  examples/test/CundallStrackTest.py
  examples/test/Damping_HM.py
  examples/test/Dem3DofGeom.py
  examples/test/WireMatPM/net-2part-displ-unloading.py
  examples/test/WireMatPM/net-2part-displ.py
  examples/test/WireMatPM/net-2part-strain.py
  examples/test/batch/sim.py
  examples/test/beam-l6geom.py
  examples/test/callback.py
  examples/test/clump.py
  examples/test/clumpPack.py
  examples/test/collider-stride-triax.py
  examples/test/collider-stride.py
  examples/test/collider-sweep-simple.py
  examples/test/energy.py
  examples/test/exact-rot-facet.py
  examples/test/exact-rot.py
  examples/test/facet-sphere-ViscElBasic-peri.py
  examples/test/facet-sphere-ViscElBasic.py
  examples/test/facet-sphere.py
  examples/test/flat-collider.py
  examples/test/force-move.py
  examples/test/force-network-video.py
  examples/test/genCylLSM.py
  examples/test/helix.py
  examples/test/interpolating-force.py
  examples/test/kinematic.py
  examples/test/mindlin.py
  examples/test/multi/multi.py
  examples/test/pack-cloud.py
  examples/test/performance/checkPerf.py
  examples/test/peri3dController_example1.py
  examples/test/peri3dController_shear.py
  examples/test/peri3dController_triaxialCompression.py
  examples/test/periodic-geom-compare.py
  examples/test/periodic-shear.py
  examples/test/periodic-simple-shear.py
  examples/test/periodic-simple.py
  examples/test/periodic-triax-settingHsize.py
  examples/test/periodic-triax.py
  examples/test/qt4-pyqglviewer.py
  examples/test/remove-body.py
  examples/test/shear.py
  examples/test/sphere-sphere-ViscElBasic-peri.py
  examples/test/spheresFactory.py
  examples/test/subdomain-balancer.py
  examples/test/test-sphere-facet-corner.py
  examples/test/test-sphere-facet.py
  examples/test/test_Ip2_FrictMat_CpmMat_FrictPhys.py
  examples/test/triax-basic.py
  examples/test/triax-cohesive.py
  examples/test/vtk-exporter/vtkExporter.py
  examples/test/wall.py
  examples/timeStepperUsage.py
  examples/triax-tutorial/script-session1.py
  examples/triax-tutorial/script-session2.py
  examples/triax-tutorial/session1-basic-triax.pdf
  gui/qt4/GLViewer.cpp
  gui/qt4/GLViewer.hpp
  gui/qt4/SerializableEditor.py
  lib/base/Math.hpp
  lib/base/openmp-accu.hpp
  lib/smoothing/WeightedAverage2d.hpp
  lib/triangulation/FlowBoundingSphere.hpp
  lib/triangulation/FlowBoundingSphere.ipp
  lib/triangulation/PeriodicFlow.cpp
  lib/triangulation/PeriodicFlow.hpp
  lib/triangulation/def_types.h
  pkg/common/Bo1_Facet_Aabb.cpp
  pkg/common/Cylinder.cpp
  pkg/common/ForceResetter.cpp
  pkg/common/Gl1_NormPhys.cpp
  pkg/common/GravityEngines.cpp
  pkg/common/Grid.cpp
  pkg/common/Grid.hpp
  pkg/common/InsertionSortCollider.cpp
  pkg/common/InteractionLoop.cpp
  pkg/common/InteractionLoop.hpp
  pkg/common/KinematicEngines.cpp
  pkg/common/OpenGLRenderer.cpp
  pkg/common/ParallelEngine.cpp
  pkg/common/PeriodicEngines.hpp
  pkg/common/ZECollider.cpp
  pkg/dem/CapillaryTriaxialTest.cpp
  pkg/dem/CohFrictMat.hpp
  pkg/dem/CohesiveFrictionalContactLaw.cpp
  pkg/dem/CohesiveTriaxialTest.cpp
  pkg/dem/ConcretePM.cpp
  pkg/dem/ConcretePM.hpp
  pkg/dem/DomainLimiter.cpp
  pkg/dem/DomainLimiter.hpp
  pkg/dem/ElasticContactLaw.cpp
  pkg/dem/ElasticContactLaw.hpp
  pkg/dem/FlowEngine.cpp
  pkg/dem/FlowEngine.hpp
  pkg/dem/GlobalStiffnessTimeStepper.cpp
  pkg/dem/GlobalStiffnessTimeStepper.hpp
  pkg/dem/Ig2_Facet_Sphere_ScGeom.cpp
  pkg/dem/Ig2_Facet_Sphere_ScGeom.hpp
  pkg/dem/Ig2_Sphere_Sphere_ScGeom.cpp
  pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.cpp
  pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.hpp
  pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.hpp
  pkg/dem/L3Geom.cpp
  pkg/dem/Law2_ScGeom_CapillaryPhys_Capillarity.cpp
  pkg/dem/Law2_ScGeom_CapillaryPhys_Capillarity.hpp
  pkg/dem/NewtonIntegrator.cpp
  pkg/dem/NewtonIntegrator.hpp
  pkg/dem/PeriIsoCompressor.cpp
  pkg/dem/SampleCapillaryPressureEngine.cpp
  pkg/dem/SampleCapillaryPressureEngine.hpp
  pkg/dem/ScGeom.hpp
  pkg/dem/Shop.cpp
  pkg/dem/Shop.hpp
  pkg/dem/SpherePack.cpp
  pkg/dem/SpherePack.hpp
  pkg/dem/TesselationWrapper.cpp
  pkg/dem/TesselationWrapper.hpp
  pkg/dem/ThreeDTriaxialEngine.cpp
  pkg/dem/TriaxialCompressionEngine.cpp
  pkg/dem/TriaxialCompressionEngine.hpp
  pkg/dem/TriaxialStateRecorder.cpp
  pkg/dem/TriaxialStressController.cpp
  pkg/dem/TriaxialStressController.hpp
  pkg/dem/TriaxialTest.cpp
  pkg/dem/VTKRecorder.cpp
  pkg/dem/VTKRecorder.hpp
  py/CMakeLists.txt
  py/__init__.py.in
  py/_eudoxos.cpp
  py/_utils.cpp
  py/bodiesHandling.py
  py/eudoxos.py
  py/export.py
  py/geom.py
  py/mathWrap/miniEigen.cpp
  py/pack/_packObb.cpp
  py/pack/_packPredicates.cpp
  py/pack/_packSpheres.cpp
  py/pack/pack.py
  py/plot.py
  py/post2d.py
  py/tests/clump.py
  py/tests/cohesive-chain.py
  py/tests/core.py
  py/tests/engines.py
  py/tests/pbc.py
  py/tests/wrapper.py
  py/timing.py
  py/utils.py
  py/wrapper/yadeWrapper.cpp
  py/ymport.py
  scripts/README


--
lp:yade
https://code.launchpad.net/~yade-pkg/yade/git-trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-pkg/yade/git-trunk/+edit-subscription
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt	2012-11-01 21:42:22 +0000
+++ CMakeLists.txt	2013-05-14 21:24:11 +0000
@@ -32,24 +32,27 @@
 INCLUDE(FindGTS)
 INCLUDE(FindGL2PS)
 INCLUDE(FindCGAL)
-
+INCLUDE(FindNumPy)
+INCLUDE(FindLoki)
+INCLUDE(FindPythonModule)
+INCLUDE(GNUInstallDirs)
 #===========================================================
 IF (CMAKE_CXX_FLAGS)
   #If flags are set, add only neccessary flags
   IF (DEBUG)
     SET(CMAKE_VERBOSE_MAKEFILE 1)
     SET(CMAKE_BUILD_TYPE Debug)
-    SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -DYADE_PTR_CAST=static_pointer_cast -DYADE_CAST=static_cast -DYADE_DEBUG -ggdb2")
+    SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DYADE_PTR_CAST=static_pointer_cast -DYADE_CAST=static_cast -DYADE_DEBUG")
   ELSE (DEBUG)
     SET(CMAKE_BUILD_TYPE Release)
     SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -DYADE_PTR_CAST=static_pointer_cast -DYADE_CAST=static_cast -fPIC")
   ENDIF (DEBUG)
 ELSE (CMAKE_CXX_FLAGS)
-  #If flags are not set, add all usefull flags
+  #If flags are not set, add all useful flags
   IF (DEBUG)
     SET(CMAKE_VERBOSE_MAKEFILE 1)
     SET(CMAKE_BUILD_TYPE Debug)
-    SET(CMAKE_CXX_FLAGS  "-DYADE_PTR_CAST=static_pointer_cast -DYADE_CAST=static_cast -DYADE_DEBUG -Wall -fPIC -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security -ggdb2")
+    SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}  -DYADE_PTR_CAST=static_pointer_cast -DYADE_CAST=static_cast -DYADE_DEBUG -Wall -fPIC -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security")
   ELSE (DEBUG)
     SET(CMAKE_BUILD_TYPE Release)
     SET(CMAKE_CXX_FLAGS  "-DYADE_PTR_CAST=static_pointer_cast -DYADE_CAST=static_cast -Wall -fPIC -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Wformat-security -Werror=format-security -s")
@@ -57,6 +60,7 @@
 ENDIF (CMAKE_CXX_FLAGS)
 #===========================================================
 # Add possibility to use local boost installation (e.g. -DLocalBoost=1.46.1)
+
 FIND_PACKAGE(Boost ${LocalBoost} COMPONENTS python thread date_time filesystem iostreams regex serialization REQUIRED)
 INCLUDE_DIRECTORIES (${Boost_INCLUDE_DIRS})
 # for checking purpose
@@ -65,7 +69,14 @@
 MESSAGE("--   Boost_INCLUDE_DIRS: " ${Boost_INCLUDE_DIRS})
 MESSAGE("--   Boost_LIBRARIES: " ${Boost_LIBRARIES})
 
-FIND_PACKAGE(Eigen3)
+#===========================================================
+FIND_PACKAGE(NumPy REQUIRED)
+INCLUDE_DIRECTORIES(${NUMPY_INCLUDE_DIRS})
+
+FIND_PACKAGE(Loki REQUIRED)
+FIND_PACKAGE(Eigen3 REQUIRED)
+#===========================================================
+
 SET(DEFAULT ON CACHE INTERNAL "Default value for enabled by default options")
 SET(LINKLIBS "")
 SET(CONFIGURED_FEATS "")
@@ -85,15 +96,6 @@
   INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR})
   MESSAGE(STATUS "Found Eigen3")
   SET(CONFIGURED_FEATS "${CONFIGURED_FEATS} Eigen3")
-ELSE (EIGEN3_FOUND)
-  FIND_PACKAGE(Eigen2)
-  if (EIGEN2_FOUND)
-    INCLUDE_DIRECTORIES(${EIGEN2_INCLUDE_DIR})
-    MESSAGE(STATUS "Found Eigen2")
-    SET(CONFIGURED_FEATS "${CONFIGURED_FEATS} Eigen2")
-  ELSE (EIGEN2_FOUND)
-    MESSAGE(FATAL_ERROR "None Eigen2 or Eigen3 were found!")
-  ENDIF (EIGEN2_FOUND)
 ENDIF(EIGEN3_FOUND)
 #===========================================================
 IF(ENABLE_VTK)
@@ -102,7 +104,7 @@
     INCLUDE_DIRECTORIES(${VTK_INCLUDE_DIRS})
     LINK_DIRECTORIES( ${VTK_LIBRARY_DIRS} )
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DYADE_VTK")
-    SET(features "${features},vtk")
+    SET(features "${features} vtk")
     MESSAGE(STATUS "Found VTK")
     SET(CONFIGURED_FEATS "${CONFIGURED_FEATS} VTK")
   ELSE(VTK_FOUND)
@@ -117,10 +119,10 @@
 IF(ENABLE_OPENMP)
   FIND_PACKAGE(OpenMP)
   IF(OPENMP_FOUND)
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DYADE_OPENMP -fopenmp")
+    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DYADE_OPENMP ${OpenMP_CXX_FLAGS}")
     MESSAGE(STATUS "Found OpenMP")
     SET(CONFIGURED_FEATS "${CONFIGURED_FEATS} OpenMP")
-    SET(features "${features},openmp")
+    SET(features "${features} openmp")
   ELSE(OPENMP_FOUND)
     MESSAGE(STATUS "OpenMP NOT found")
     SET(ENABLE_OPENMP OFF)
@@ -140,7 +142,7 @@
     INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS})
     MESSAGE(STATUS "Found GTS")
     SET(CONFIGURED_FEATS "${CONFIGURED_FEATS} GTS")
-    SET(features "${features},gts")
+    SET(features "${features} gts")
   ELSE(GTS_FOUND AND GLIB2_FOUND)
     MESSAGE(STATUS "GTS NOT found")
     SET(DISABLED_FEATS "${DISABLED_FEATS} GTS")
@@ -159,7 +161,7 @@
   IF(QT4_FOUND AND OPENGL_FOUND AND GLUT_FOUND AND GLIB2_FOUND AND QGLVIEWER_FOUND)
     SET(GUI_LIBS ${GLUT_LIBRARY} ${OPENGL_LIBRARY} ${QGLVIEWER_LIBRARIES})
     SET(GUI_SRC_LIB "lib/opengl/GLUtils.cpp")
-    SET(features "${features},qt4,opengl")
+    SET(features "${features} qt4 opengl")
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DYADE_OPENGL")
     INCLUDE_DIRECTORIES(${GLIB2_INCLUDE_DIRS})
     INCLUDE_DIRECTORIES(${QT_INCLUDES})
@@ -175,6 +177,16 @@
   SET(DISABLED_FEATS "${DISABLED_FEATS} GUI")
 ENDIF(ENABLE_GUI)
 #===========================================================
+# This one will automatically enable CGAL
+IF(ENABLE_PFVFLOW)
+  IF (NOT ENABLE_CGAL)
+    MESSAGE(STATUS "PFVFLOW depends on CGAL, attempting to turn ENABLE_CGAL ON")
+    SET(ENABLE_CGAL ON)
+  ENDIF (NOT ENABLE_CGAL)
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFLOW_ENGINE")
+  SET(CONFIGURED_FEATS "${CONFIGURED_FEATS} PFVflow")
+ENDIF(ENABLE_PFVFLOW)
+#===========================================================
 IF(ENABLE_CGAL)  
   INCLUDE(FindGMP)
   FIND_PACKAGE(CGAL)
@@ -212,7 +224,7 @@
     SET(ENABLE_LINSOLV OFF)
   ENDIF(CHOLMOD_FOUND)
 ENDIF(ENABLE_LINSOLV)
-#===========================================================
+#===============================================
 IF(ENABLE_GL2PS)
   FIND_PACKAGE(GL2PS)
   IF(GL2PS_FOUND)
@@ -253,7 +265,7 @@
 ENDIF(NOSUFFIX)   #For packaging
 
 IF(NOT LIBRARY_OUTPUT_PATH)   #For packaging
-  SET (LIBRARY_OUTPUT_PATH "lib")
+  SET (LIBRARY_OUTPUT_PATH ${CMAKE_INSTALL_LIBDIR})
 ENDIF(NOT LIBRARY_OUTPUT_PATH)   #For packaging
 
 IF (NOT runtimePREFIX)
@@ -266,9 +278,10 @@
 #===========================================================
 
 SET(YADE_LIB_PATH ${CMAKE_INSTALL_PREFIX}/${LIBRARY_OUTPUT_PATH}/yade${SUFFIX})
-SET(YADE_EXEC_PATH ${CMAKE_INSTALL_PREFIX}/bin)
+SET(YADE_EXEC_PATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
 SET(YADE_PY_PATH ${YADE_LIB_PATH}/py)
-SET(YADE_DOC_PATH ${CMAKE_INSTALL_PREFIX}/share/doc/yade${SUFFIX})
+SET(YADE_DOC_PATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/doc/yade${SUFFIX})
+SET(YADE_MAN_PATH ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_MANDIR})
 
 
 SET(CMAKE_SKIP_BUILD_RPATH FALSE)
@@ -318,13 +331,21 @@
   ADD_LIBRARY(support SHARED ${SRC_LIB})
 ENDIF (CHUNKSIZE)
 #===========================================================
+find_python_module(minieigen)
+IF (PY_minieigen)
+  MESSAGE(STATUS "Use system minieigen version")
+ELSE (PY_minieigen)
+  MESSAGE(STATUS "Use embedded version of minieigen. Please, consider installing the corresponding package")
+ENDIF (PY_minieigen)
+find_python_module(Tkinter REQUIRED)
+#===========================================================
 
 ADD_LIBRARY(boot SHARED ${CMAKE_CURRENT_SOURCE_DIR}/core/main/pyboot.cpp)
 SET_TARGET_PROPERTIES(boot PROPERTIES PREFIX "")
 TARGET_LINK_LIBRARIES(support ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${LINKLIBS})
 TARGET_LINK_LIBRARIES(core support ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${LINKLIBS} -lrt)
+TARGET_LINK_LIBRARIES(boot plugins support core ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${LINKLIBS})
 
-TARGET_LINK_LIBRARIES(plugins support core miniEigen ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} ${LINKLIBS})
 IF(ENABLE_VTK)
   TARGET_LINK_LIBRARIES(plugins vtkHybrid)
 ENDIF(ENABLE_VTK)
@@ -334,11 +355,13 @@
   TARGET_LINK_LIBRARIES(support ${GUI_LIBS})
 ENDIF(ENABLE_GUI)
 
-TARGET_LINK_LIBRARIES(boot plugins support core ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
-ADD_LIBRARY(miniEigen SHARED py/mathWrap/miniEigen.cpp)
-SET_TARGET_PROPERTIES(miniEigen PROPERTIES PREFIX "")
-TARGET_LINK_LIBRARIES(miniEigen ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
-
+#====================================
+IF (NOT (PY_minieigen))
+  ADD_LIBRARY(miniEigen SHARED py/mathWrap/miniEigen.cpp)
+  SET_TARGET_PROPERTIES(miniEigen PROPERTIES PREFIX "")
+  TARGET_LINK_LIBRARIES(miniEigen ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
+  INSTALL(TARGETS miniEigen DESTINATION ${YADE_PY_PATH})
+ENDIF (NOT (PY_minieigen))
 #====================================
 #Back compatibility with scons
 SET (realVersion ${YADE_VERSION})
@@ -370,7 +393,7 @@
 INSTALL(TARGETS core DESTINATION ${YADE_LIB_PATH})
 INSTALL(TARGETS plugins DESTINATION ${YADE_LIB_PATH})
 INSTALL(TARGETS support DESTINATION ${YADE_LIB_PATH})
-INSTALL(TARGETS miniEigen DESTINATION ${YADE_PY_PATH})
+
 #===========================================================
 MESSAGE(STATUS "===========================================================")
 MESSAGE(STATUS "Yade configured with following features:${CONFIGURED_FEATS}")
@@ -381,7 +404,7 @@
   MESSAGE(STATUS "Optimized build")
 ENDIF (DEBUG)
 IF (CHUNKSIZE)
-  MESSAGE(STATUS "CHUNKSIZE ist set to " ${CHUNKSIZE})
+  MESSAGE(STATUS "CHUNKSIZE is set to " ${CHUNKSIZE})
 ENDIF (CHUNKSIZE)
 MESSAGE(STATUS "===========================================================")
 #===========================================================
@@ -404,3 +427,40 @@
                   WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/doc/sphinx/_build/latex
                   DEPENDS ${YADE_EXEC_PATH}/yade${SUFFIX} ${CMAKE_BINARY_DIR}/doc/sphinx/_build/latex/Yade.tex
                   )
+ADD_CUSTOM_COMMAND( 
+                  TARGET doc POST_BUILD
+                  COMMAND rm -rf ${YADE_DOC_PATH}/html
+                  COMMAND mv ${CMAKE_BINARY_DIR}/doc/sphinx/_build/html ${YADE_DOC_PATH}/html
+                  COMMAND mv ${CMAKE_BINARY_DIR}/doc/sphinx/_build/latex/Yade.pdf ${YADE_DOC_PATH}/
+                  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/doc/sphinx/_build/latex
+                  DEPENDS ${YADE_EXEC_PATH}/yade${SUFFIX} ${CMAKE_BINARY_DIR}/doc/sphinx/_build/latex/Yade.tex
+                  )
+ADD_CUSTOM_COMMAND( 
+                  TARGET doc POST_BUILD
+                  COMMAND mv ${CMAKE_BINARY_DIR}/doc/sphinx/_build/epub/Yade.epub ${YADE_DOC_PATH}/ || true
+                  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/doc/sphinx/_build/latex
+                  DEPENDS ${YADE_EXEC_PATH}/yade${SUFFIX} ${CMAKE_BINARY_DIR}/doc/sphinx/_build/latex/Yade.tex
+                  )
+#===========================================================
+#Building manpage
+ADD_CUSTOM_TARGET(manpage)
+ADD_CUSTOM_COMMAND( 
+                  TARGET manpage POST_BUILD
+                  COMMAND help2man ${YADE_EXEC_PATH}/yade${SUFFIX} > yade${SUFFIX}.1
+                  COMMAND help2man ${YADE_EXEC_PATH}/yade${SUFFIX}-batch > yade${SUFFIX}-batch.1
+                  COMMAND mkdir -p ${YADE_MAN_PATH}
+                  COMMAND mv *.1 ${YADE_MAN_PATH}
+                  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+                  DEPENDS ${YADE_EXEC_PATH}/yade${SUFFIX} /usr/bin/help2man
+                  )
+#===========================================================
+#Execute standard checks
+ADD_CUSTOM_TARGET(check)
+ADD_CUSTOM_COMMAND( 
+                  TARGET check POST_BUILD
+                  COMMAND ${YADE_EXEC_PATH}/yade${SUFFIX} --test
+                  COMMAND ${YADE_EXEC_PATH}/yade${SUFFIX} --check
+                  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+                  DEPENDS ${YADE_EXEC_PATH}/yade${SUFFIX}
+                  )
+#===========================================================

=== modified file 'README.rst'
--- README.rst	2012-08-23 18:41:11 +0000
+++ README.rst	2013-04-26 20:00:56 +0000
@@ -12,6 +12,7 @@
 
 - https://www.yade-dem.org/doc/ (includes c++ and python reference)
 - https://yade-dem.org/doc/Yade.pdf (PDF-file with documentation)
+- https://yade-dem.org/doc/Yade.epub (EPUB-file with documentation)
  
 **Downloads:**
 
@@ -21,9 +22,9 @@
   - Daily-builds: https://launchpad.net/~yade-pkg/+archive/snapshots
   - External packages: https://launchpad.net/~yade-users/+archive/external
 
-- Tarballs of different revisions: 
+- Tarballs of different versions: 
 
-  - https://www.yade-dem.org/source/
+  - https://github.com/yade/trunk/tags
   - Repository on github.com: https://github.com/yade
   - Repository on git.debian.org: http://git.debian.org/?p=debian-science/packages/yade.git
 

=== removed file 'cMake/FindEigen2.cmake'
--- cMake/FindEigen2.cmake	2012-05-07 17:30:10 +0000
+++ cMake/FindEigen2.cmake	1970-01-01 00:00:00 +0000
@@ -1,74 +0,0 @@
-# - Try to find Eigen2 lib
-# Once done this will define
-#
-#  EIGEN2_FOUND - system has eigen lib with correct version
-#  EIGEN2_INCLUDE_DIR - the eigen include directory
-#  EIGEN2_VERSION - eigen version
-
-# Copyright (c) 2006, 2007 Montel Laurent, <montel@xxxxxxx>
-# Copyright (c) 2008, 2009 Gael Guennebaud, <g.gael@xxxxxxx>
-# Redistribution and use is allowed according to the terms of the BSD license.
-
-if(NOT EIGEN2_MIN_VERSION)
-  if(NOT Eigen2_FIND_VERSION_MAJOR)
-    set(Eigen2_FIND_VERSION_MAJOR 2)
-  endif(NOT Eigen2_FIND_VERSION_MAJOR)
-  if(NOT Eigen2_FIND_VERSION_MINOR)
-    set(Eigen2_FIND_VERSION_MINOR 0)
-  endif(NOT Eigen2_FIND_VERSION_MINOR)
-  if(NOT Eigen2_FIND_VERSION_PATCH)
-    set(Eigen2_FIND_VERSION_PATCH 0)
-  endif(NOT Eigen2_FIND_VERSION_PATCH)
-
-  set(EIGEN2_MIN_VERSION "${Eigen2_FIND_VERSION_MAJOR}.${Eigen2_FIND_VERSION_MINOR}.${Eigen2_FIND_VERSION_PATCH}")
-endif(NOT EIGEN2_MIN_VERSION)
-
-macro(_eigen2_check_version)
-  file(READ "${EIGEN2_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen2_version_header LIMIT 5000 OFFSET 1000)
-
-  string(REGEX MATCH "define *EIGEN_WORLD_VERSION ([0-9]*)" _eigen2_world_version_match "${_eigen2_version_header}")
-  set(EIGEN2_WORLD_VERSION "${CMAKE_MATCH_1}")
-  string(REGEX MATCH "define *EIGEN_MAJOR_VERSION ([0-9]*)" _eigen2_major_version_match "${_eigen2_version_header}")
-  set(EIGEN2_MAJOR_VERSION "${CMAKE_MATCH_1}")
-  string(REGEX MATCH "define *EIGEN_MINOR_VERSION ([0-9]*)" _eigen2_minor_version_match "${_eigen2_version_header}")
-  set(EIGEN2_MINOR_VERSION "${CMAKE_MATCH_1}")
-
-  set(EIGEN2_VERSION ${EIGEN2_WORLD_VERSION}.${EIGEN2_MAJOR_VERSION}.${EIGEN2_MINOR_VERSION})
-  if(${EIGEN2_VERSION} VERSION_LESS ${EIGEN2_MIN_VERSION})
-    set(EIGEN2_VERSION_OK FALSE)
-  else(${EIGEN2_VERSION} VERSION_LESS ${EIGEN2_MIN_VERSION})
-    set(EIGEN2_VERSION_OK TRUE)
-  endif(${EIGEN2_VERSION} VERSION_LESS ${EIGEN2_MIN_VERSION})
-
-  if(NOT EIGEN2_VERSION_OK)
-  
-    message(STATUS "Eigen2 version ${EIGEN2_VERSION} found in ${EIGEN2_INCLUDE_DIR}, "
-                   "but at least version ${EIGEN2_MIN_VERSION} is required")
-  endif(NOT EIGEN2_VERSION_OK)
-endmacro(_eigen2_check_version)
-
-if (EIGEN2_INCLUDE_DIR)
-
-  # in cache already
-  _eigen2_check_version()
-  set(EIGEN2_FOUND ${EIGEN2_VERSION_OK})
-
-else (EIGEN2_INCLUDE_DIR)
-
-find_path(EIGEN2_INCLUDE_DIR NAMES Eigen/Core
-     PATHS
-     ${INCLUDE_INSTALL_DIR}
-     ${KDE4_INCLUDE_DIR}
-     PATH_SUFFIXES eigen2
-   )
-
-if(EIGEN2_INCLUDE_DIR)
-  _eigen2_check_version()
-endif(EIGEN2_INCLUDE_DIR)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(Eigen2 DEFAULT_MSG EIGEN2_INCLUDE_DIR EIGEN2_VERSION_OK)
-
-mark_as_advanced(EIGEN2_INCLUDE_DIR)
-
-endif(EIGEN2_INCLUDE_DIR)

=== added file 'cMake/FindLoki.cmake'
--- cMake/FindLoki.cmake	1970-01-01 00:00:00 +0000
+++ cMake/FindLoki.cmake	2013-01-29 16:16:15 +0000
@@ -0,0 +1,16 @@
+# - Find Loki library
+# Find the native GL2PS includes and library
+# This module defines
+#  LOKI_INCLUDE_DIR, where to find loki/Typelist.h, etc.
+#  LOKI_LIBRARY, libraries to link against to use GL2PS.
+#  LOKI_FOUND, If false, do not try to use GL2PS.
+
+FIND_PATH(LOKI_INCLUDE_DIR loki/Typelist.h)
+FIND_LIBRARY(LOKI_LIBRARY NAMES loki )
+
+# handle the QUIETLY and REQUIRED arguments and set LOKI_FOUND to TRUE if
+# all listed variables are TRUE
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Loki  DEFAULT_MSG  LOKI_INCLUDE_DIR LOKI_LIBRARY)
+
+MARK_AS_ADVANCED(LOKI_INCLUDE_DIR LOKI_LIBRARY)

=== added file 'cMake/FindNumPy.cmake'
--- cMake/FindNumPy.cmake	1970-01-01 00:00:00 +0000
+++ cMake/FindNumPy.cmake	2013-01-25 16:07:21 +0000
@@ -0,0 +1,94 @@
+# https://github.com/ContinuumIO/dynd-python/blob/master/FindNumPy.cmake
+
+# - Find the NumPy libraries
+# This module finds if NumPy is installed, and sets the following variables
+# indicating where it is.
+#
+# TODO: Update to provide the libraries and paths for linking npymath lib.
+#
+#  NUMPY_FOUND               - was NumPy found
+#  NUMPY_VERSION             - the version of NumPy found as a string
+#  NUMPY_VERSION_MAJOR       - the major version number of NumPy
+#  NUMPY_VERSION_MINOR       - the minor version number of NumPy
+#  NUMPY_VERSION_PATCH       - the patch version number of NumPy
+#  NUMPY_VERSION_DECIMAL     - e.g. version 1.6.1 is 10601
+#  NUMPY_INCLUDE_DIRS        - path to the NumPy include files
+
+#============================================================================
+# Copyright 2012 Continuum Analytics, Inc.
+#
+# MIT License
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to permit
+# persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+# 
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+# 
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+# 
+#============================================================================
+
+# Finding NumPy involves calling the Python interpreter
+if(NumPy_FIND_REQUIRED)
+    find_package(PythonInterp REQUIRED)
+else()
+    find_package(PythonInterp)
+endif()
+
+if(NOT PYTHONINTERP_FOUND)
+    set(NUMPY_FOUND FALSE)
+    return()
+endif()
+
+execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
+    "import numpy as n; print(n.__version__); print(n.get_include());"
+    RESULT_VARIABLE _NUMPY_SEARCH_SUCCESS
+    OUTPUT_VARIABLE _NUMPY_VALUES
+    ERROR_VARIABLE _NUMPY_ERROR_VALUE
+    OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+if(NOT _NUMPY_SEARCH_SUCCESS MATCHES 0)
+    if(NumPy_FIND_REQUIRED)
+        message(FATAL_ERROR
+            "NumPy import failure:\n${_NUMPY_ERROR_VALUE}")
+    endif()
+    set(NUMPY_FOUND FALSE)
+    return()
+endif()
+
+# Convert the process output into a list
+string(REGEX REPLACE ";" "\\\\;" _NUMPY_VALUES ${_NUMPY_VALUES})
+string(REGEX REPLACE "\n" ";" _NUMPY_VALUES ${_NUMPY_VALUES})
+list(GET _NUMPY_VALUES 0 NUMPY_VERSION)
+list(GET _NUMPY_VALUES 1 NUMPY_INCLUDE_DIRS)
+
+# Make sure all directory separators are '/'
+string(REGEX REPLACE "\\\\" "/" NUMPY_INCLUDE_DIRS ${NUMPY_INCLUDE_DIRS})
+
+# Get the major and minor version numbers
+string(REGEX REPLACE "\\." ";" _NUMPY_VERSION_LIST ${NUMPY_VERSION})
+list(GET _NUMPY_VERSION_LIST 0 NUMPY_VERSION_MAJOR)
+list(GET _NUMPY_VERSION_LIST 1 NUMPY_VERSION_MINOR)
+list(GET _NUMPY_VERSION_LIST 2 NUMPY_VERSION_PATCH)
+string(REGEX MATCH "[0-9]*" NUMPY_VERSION_PATCH ${NUMPY_VERSION_PATCH})
+math(EXPR NUMPY_VERSION_DECIMAL
+    "(${NUMPY_VERSION_MAJOR} * 10000) + (${NUMPY_VERSION_MINOR} * 100) + ${NUMPY_VERSION_PATCH}")
+
+find_package_message(NUMPY
+    "Found NumPy: version \"${NUMPY_VERSION}\" ${NUMPY_INCLUDE_DIRS}"
+    "${NUMPY_INCLUDE_DIRS}${NUMPY_VERSION}")
+
+set(NUMPY_FOUND TRUE)
+

=== added file 'cMake/FindPythonModule.cmake'
--- cMake/FindPythonModule.cmake	1970-01-01 00:00:00 +0000
+++ cMake/FindPythonModule.cmake	2013-03-08 21:26:47 +0000
@@ -0,0 +1,23 @@
+# http://www.cmake.org/pipermail/cmake/2011-January/041666.html
+#
+# - Find Python Module
+
+FUNCTION(find_python_module module)
+  STRING(TOUPPER ${module} module_upper)
+  
+  IF(ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED")
+    SET(${module}_FIND_REQUIRED TRUE)
+  ENDIF(ARGC GREATER 1 AND ARGV1 STREQUAL "REQUIRED")
+  
+  EXECUTE_PROCESS(COMMAND "${PYTHON_EXECUTABLE}" "-c" 
+    "import re, ${module}; print re.compile('/__init__.py.*').sub('',${module}.__file__)"
+    RESULT_VARIABLE _${module}_status 
+    OUTPUT_VARIABLE _${module}_location
+    ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
+    
+    IF(_${module}_status MATCHES 0)
+      SET(PY_${module} ${_${module}_location} CACHE STRING "Location of Python module ${module}")
+    ENDIF(_${module}_status MATCHES 0)
+    
+  FIND_PACKAGE_HANDLE_STANDARD_ARGS(${module} DEFAULT_MSG PY_${module})
+ENDFUNCTION(find_python_module)

=== added file 'cMake/GNUInstallDirs.cmake'
--- cMake/GNUInstallDirs.cmake	1970-01-01 00:00:00 +0000
+++ cMake/GNUInstallDirs.cmake	2013-04-18 17:32:17 +0000
@@ -0,0 +1,188 @@
+# - Define GNU standard installation directories
+# Provides install directory variables as defined for GNU software:
+#  http://www.gnu.org/prep/standards/html_node/Directory-Variables.html
+# Inclusion of this module defines the following variables:
+#  CMAKE_INSTALL_<dir>      - destination for files of a given type
+#  CMAKE_INSTALL_FULL_<dir> - corresponding absolute path
+# where <dir> is one of:
+#  BINDIR           - user executables (bin)
+#  SBINDIR          - system admin executables (sbin)
+#  LIBEXECDIR       - program executables (libexec)
+#  SYSCONFDIR       - read-only single-machine data (etc)
+#  SHAREDSTATEDIR   - modifiable architecture-independent data (com)
+#  LOCALSTATEDIR    - modifiable single-machine data (var)
+#  LIBDIR           - object code libraries (lib or lib64 or lib/<multiarch-tuple> on Debian)
+#  INCLUDEDIR       - C header files (include)
+#  OLDINCLUDEDIR    - C header files for non-gcc (/usr/include)
+#  DATAROOTDIR      - read-only architecture-independent data root (share)
+#  DATADIR          - read-only architecture-independent data (DATAROOTDIR)
+#  INFODIR          - info documentation (DATAROOTDIR/info)
+#  LOCALEDIR        - locale-dependent data (DATAROOTDIR/locale)
+#  MANDIR           - man documentation (DATAROOTDIR/man)
+#  DOCDIR           - documentation root (DATAROOTDIR/doc/PROJECT_NAME)
+# Each CMAKE_INSTALL_<dir> value may be passed to the DESTINATION options of
+# install() commands for the corresponding file type.  If the includer does
+# not define a value the above-shown default will be used and the value will
+# appear in the cache for editing by the user.
+# Each CMAKE_INSTALL_FULL_<dir> value contains an absolute path constructed
+# from the corresponding destination by prepending (if necessary) the value
+# of CMAKE_INSTALL_PREFIX.
+
+#=============================================================================
+# Copyright 2011 Nikita Krupen'ko <krnekit@xxxxxxxxx>
+# Copyright 2011 Kitware, Inc.
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+# (To distribute this file outside of CMake, substitute the full
+#  License text for the above reference.)
+
+# Installation directories
+#
+if(NOT DEFINED CMAKE_INSTALL_BINDIR)
+  set(CMAKE_INSTALL_BINDIR "bin" CACHE PATH "user executables (bin)")
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_SBINDIR)
+  set(CMAKE_INSTALL_SBINDIR "sbin" CACHE PATH "system admin executables (sbin)")
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_LIBEXECDIR)
+  set(CMAKE_INSTALL_LIBEXECDIR "libexec" CACHE PATH "program executables (libexec)")
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_SYSCONFDIR)
+  set(CMAKE_INSTALL_SYSCONFDIR "etc" CACHE PATH "read-only single-machine data (etc)")
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_SHAREDSTATEDIR)
+  set(CMAKE_INSTALL_SHAREDSTATEDIR "com" CACHE PATH "modifiable architecture-independent data (com)")
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_LOCALSTATEDIR)
+  set(CMAKE_INSTALL_LOCALSTATEDIR "var" CACHE PATH "modifiable single-machine data (var)")
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
+  set(_LIBDIR_DEFAULT "lib")
+  # Override this default 'lib' with 'lib64' iff:
+  #  - we are on Linux system but NOT cross-compiling
+  #  - we are NOT on debian
+  #  - we are on a 64 bits system
+  # reason is: amd64 ABI: http://www.x86-64.org/documentation/abi.pdf
+  # For Debian with multiarch, use 'lib/${CMAKE_LIBRARY_ARCHITECTURE}' if
+  # CMAKE_LIBRARY_ARCHITECTURE is set (which contains e.g. "i386-linux-gnu"
+  # See http://wiki.debian.org/Multiarch
+  if((CMAKE_SYSTEM_NAME MATCHES "Linux|kFreeBSD" OR CMAKE_SYSTEM_NAME STREQUAL "GNU")
+      AND NOT CMAKE_CROSSCOMPILING)
+    if (EXISTS "/etc/debian_version") # is this a debian system ?
+       if(CMAKE_LIBRARY_ARCHITECTURE)
+         set(_LIBDIR_DEFAULT "lib/${CMAKE_LIBRARY_ARCHITECTURE}")
+       endif()
+    else() # not debian, rely on CMAKE_SIZEOF_VOID_P:
+      if(NOT DEFINED CMAKE_SIZEOF_VOID_P)
+        message(AUTHOR_WARNING
+          "Unable to determine default CMAKE_INSTALL_LIBDIR directory because no target architecture is known. "
+          "Please enable at least one language before including GNUInstallDirs.")
+      else()
+        if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
+          set(_LIBDIR_DEFAULT "lib64")
+        endif()
+      endif()
+    endif()
+  endif()
+  set(CMAKE_INSTALL_LIBDIR "${_LIBDIR_DEFAULT}" CACHE PATH "object code libraries (${_LIBDIR_DEFAULT})")
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
+  set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE PATH "C header files (include)")
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_OLDINCLUDEDIR)
+  set(CMAKE_INSTALL_OLDINCLUDEDIR "/usr/include" CACHE PATH "C header files for non-gcc (/usr/include)")
+endif()
+
+if(NOT DEFINED CMAKE_INSTALL_DATAROOTDIR)
+  set(CMAKE_INSTALL_DATAROOTDIR "share" CACHE PATH "read-only architecture-independent data root (share)")
+endif()
+
+#-----------------------------------------------------------------------------
+# Values whose defaults are relative to DATAROOTDIR.  Store empty values in
+# the cache and store the defaults in local variables if the cache values are
+# not set explicitly.  This auto-updates the defaults as DATAROOTDIR changes.
+
+if(NOT CMAKE_INSTALL_DATADIR)
+  set(CMAKE_INSTALL_DATADIR "" CACHE PATH "read-only architecture-independent data (DATAROOTDIR)")
+  set(CMAKE_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}")
+endif()
+
+if(NOT CMAKE_INSTALL_INFODIR)
+  set(CMAKE_INSTALL_INFODIR "" CACHE PATH "info documentation (DATAROOTDIR/info)")
+  set(CMAKE_INSTALL_INFODIR "${CMAKE_INSTALL_DATAROOTDIR}/info")
+endif()
+
+if(NOT CMAKE_INSTALL_LOCALEDIR)
+  set(CMAKE_INSTALL_LOCALEDIR "" CACHE PATH "locale-dependent data (DATAROOTDIR/locale)")
+  set(CMAKE_INSTALL_LOCALEDIR "${CMAKE_INSTALL_DATAROOTDIR}/locale")
+endif()
+
+if(NOT CMAKE_INSTALL_MANDIR)
+  set(CMAKE_INSTALL_MANDIR "" CACHE PATH "man documentation (DATAROOTDIR/man)")
+  set(CMAKE_INSTALL_MANDIR "${CMAKE_INSTALL_DATAROOTDIR}/man")
+endif()
+
+if(NOT CMAKE_INSTALL_DOCDIR)
+  set(CMAKE_INSTALL_DOCDIR "" CACHE PATH "documentation root (DATAROOTDIR/doc/PROJECT_NAME)")
+  set(CMAKE_INSTALL_DOCDIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${PROJECT_NAME}")
+endif()
+
+#-----------------------------------------------------------------------------
+
+mark_as_advanced(
+  CMAKE_INSTALL_BINDIR
+  CMAKE_INSTALL_SBINDIR
+  CMAKE_INSTALL_LIBEXECDIR
+  CMAKE_INSTALL_SYSCONFDIR
+  CMAKE_INSTALL_SHAREDSTATEDIR
+  CMAKE_INSTALL_LOCALSTATEDIR
+  CMAKE_INSTALL_LIBDIR
+  CMAKE_INSTALL_INCLUDEDIR
+  CMAKE_INSTALL_OLDINCLUDEDIR
+  CMAKE_INSTALL_DATAROOTDIR
+  CMAKE_INSTALL_DATADIR
+  CMAKE_INSTALL_INFODIR
+  CMAKE_INSTALL_LOCALEDIR
+  CMAKE_INSTALL_MANDIR
+  CMAKE_INSTALL_DOCDIR
+  )
+
+# Result directories
+#
+foreach(dir
+    BINDIR
+    SBINDIR
+    LIBEXECDIR
+    SYSCONFDIR
+    SHAREDSTATEDIR
+    LOCALSTATEDIR
+    LIBDIR
+    INCLUDEDIR
+    OLDINCLUDEDIR
+    DATAROOTDIR
+    DATADIR
+    INFODIR
+    LOCALEDIR
+    MANDIR
+    DOCDIR
+    )
+  if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
+    set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
+  else()
+    set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
+  endif()
+endforeach()

=== modified file 'core/Body.cpp'
--- core/Body.cpp	2010-12-22 10:55:23 +0000
+++ core/Body.cpp	2013-02-19 07:07:27 +0000
@@ -13,11 +13,10 @@
 
 // return list of interactions of this particle
 python::list Body::py_intrs(){
-	Scene* scene=Omega::instance().getScene().get(); // potentially unsafe with multiple simulations
 	python::list ret;
-	FOREACH(const shared_ptr<Interaction>& I, *scene->interactions){
-		if(!I->isReal()) continue;
-		if(I->getId1()==id || I->getId2()==id) ret.append(I);
+	for(Body::MapId2IntrT::iterator it=this->intrs.begin(),end=this->intrs.end(); it!=end; ++it) {  //Iterate over all bodie's interactions
+		if(!(*it).second->isReal()) continue;
+		ret.append((*it).second);
 	}
 	return ret;
 }

=== modified file 'core/BodyContainer.cpp'
--- core/BodyContainer.cpp	2012-08-01 18:58:16 +0000
+++ core/BodyContainer.cpp	2013-02-19 06:53:16 +0000
@@ -65,10 +65,8 @@
 	}
 	
 	const shared_ptr<Scene>& scene=Omega::instance().getScene();
-	FOREACH(const shared_ptr<Interaction>& i, *scene->interactions){
-		if((i->getId1()==id or i->getId2()==id)) {
-			scene->interactions->requestErase(i->getId1(),i->getId2());
-		}
+	for(Body::MapId2IntrT::iterator it=b->intrs.begin(),end=b->intrs.end(); it!=end; ++it) {  //Iterate over all bodie's interactions
+		scene->interactions->requestErase((*it).second);
 	}
 	body[id]=shared_ptr<Body>();
 	

=== modified file 'core/BodyContainer.hpp'
--- core/BodyContainer.hpp	2012-05-21 21:04:07 +0000
+++ core/BodyContainer.hpp	2013-03-06 17:30:45 +0000
@@ -17,7 +17,7 @@
 class InteractionContainer;
 
 #if YADE_OPENMP
-	#define YADE_PARALLEL_FOREACH_BODY_BEGIN(b_,bodies) const Body::id_t _sz(bodies->size()); _Pragma("omp parallel for") for(Body::id_t _id=0; _id<_sz; _id++){ if(unlikely(!(*bodies)[_id]))  continue; b_((*bodies)[_id]);
+	#define YADE_PARALLEL_FOREACH_BODY_BEGIN(b_,bodies) const Body::id_t _sz(bodies->size()); _Pragma("omp parallel for") for(Body::id_t _id=0; _id<_sz; _id++){ if(!(*bodies)[_id])  continue; b_((*bodies)[_id]);
 	#define YADE_PARALLEL_FOREACH_BODY_END() }
 #else
 	#define YADE_PARALLEL_FOREACH_BODY_BEGIN(b,bodies) FOREACH(b,*(bodies)){

=== modified file 'core/Cell.cpp'
--- core/Cell.cpp	2011-09-20 10:58:18 +0000
+++ core/Cell.cpp	2013-04-09 11:46:11 +0000
@@ -10,6 +10,8 @@
 	trsf+=_trsfInc*trsf;
 	_invTrsf=trsf.inverse();
 	// hSize contains colums with updated base vectors
+	prevHSize=hSize;
+	_vGradTimesPrevH = velGrad*prevHSize;
 	hSize+=_trsfInc*hSize;
 	if(hSize.determinant()==0){ throw runtime_error("Cell is degenerate (zero volume)."); }
 	// lengths of transformed cell vectors, skew cosines

=== modified file 'core/Cell.hpp'
--- core/Cell.hpp	2012-11-22 14:32:53 +0000
+++ core/Cell.hpp	2013-05-14 21:24:11 +0000
@@ -54,6 +54,7 @@
 	private:
 		Matrix3r _invTrsf;
 		Matrix3r _trsfInc;
+		Matrix3r _vGradTimesPrevH;
 		Vector3r _size, _cos;
 		Vector3r _refSize;
 		bool _hasShear;
@@ -89,7 +90,7 @@
 
 	// relative position and velocity for interaction accross multiple cells
 	Vector3r intrShiftPos(const Vector3i& cellDist) const { return hSize*cellDist.cast<Real>(); }
-	Vector3r intrShiftVel(const Vector3i& cellDist) const { return velGrad*hSize*cellDist.cast<Real>(); }
+	Vector3r intrShiftVel(const Vector3i& cellDist) const { return _vGradTimesPrevH*cellDist.cast<Real>(); }
 	// return body velocity while taking away mean field velocity (coming from velGrad) if the mean field velocity is applied on velocity
 	Vector3r bodyFluctuationVel(const Vector3r& pos, const Vector3r& vel, const Matrix3r& prevVelGrad) const { return (vel-prevVelGrad*pos); }
 
@@ -99,6 +100,8 @@
 	// set current transformation; has no influence on current configuration (hSize); sets display refHSize as side-effect
 	Matrix3r getTrsf() const { return trsf; }
 	void setTrsf(const Matrix3r& m){ trsf=m; postLoad(*this); }
+	Matrix3r getVelGrad() const { return velGrad; }
+	void setVelGrad(const Matrix3r& m){ nextVelGrad=m; velGradChanged=true;}
 	//BEGIN Deprecated (see refSize property)
 	// get undeformed shape
 	Matrix3r getHSize0() const { return _invTrsf*hSize; }
@@ -149,10 +152,13 @@
 		((Matrix3r,trsf,Matrix3r::Identity(),,"[overridden]")) //"Current transformation matrix of the cell, which defines how far is the current cell geometry (:yref:`hSize<Cell.hSize>`) from the reference configuration. Changing trsf will not change :yref:`hSize<Cell.hSize>`, it serves only as accumulator for transformations applied via :yref:`velGrad<Cell.velGrad>`."))
 		((Matrix3r,refHSize,Matrix3r::Identity(),,"Reference cell configuration, only used with :yref:`OpenGLRenderer.dispScale`. Updated automatically when :yref:`hSize<Cell.hSize>` or :yref:`trsf<Cell.trsf>` is assigned directly; also modified by :yref:`yade.utils.setRefSe3` (called e.g. by the :gui:`Reference` button in the UI)."))
 		((Matrix3r,hSize,Matrix3r::Identity(),,"[overridden below]"))
+		((Matrix3r,prevHSize,Matrix3r::Identity(),Attr::readonly,":yref:`hSize<Cell.hSize>` from the previous step, used in the definition of relative velocity across periods."))
 		/* normal attributes */
-		((Matrix3r,velGrad,Matrix3r::Zero(),,"Velocity gradient of the transformation; used in :yref:`NewtonIntegrator`. Values of :yref:`velGrad<Cell.velGrad>` accumulate in :yref:`trsf<Cell.trsf>` at every step."))
+		((Matrix3r,velGrad,Matrix3r::Zero(),,"[overridden below]"))
+		((Matrix3r,nextVelGrad,Matrix3r::Zero(),Attr::readonly,"see :yref:`Cell.velGrad`."))
 		((Matrix3r,prevVelGrad,Matrix3r::Zero(),Attr::readonly,"Velocity gradient in the previous step."))
-		((bool,homoDeform,true,,"Deform (:yref:`velGrad<Cell.velGrad>`) the cell homothetically, by adjusting positions and velocities of bodies. The velocity change is obtained by deriving the expression v=∇v.x, where ∇v is the macroscopic velocity gradient, giving in an incremental form: Δv=Δ ∇v x + ∇v Δx. As a result, velocities are modified as soon as ``velGrad`` changes, according to the first term: Δv(t)=Δ ∇v x(t), while the 2nd term reflects a convective term: Δv'= ∇v v(t-dt/2).")),
+		((bool,homoDeform,true,,"Deform (:yref:`velGrad<Cell.velGrad>`) the cell homothetically, by adjusting positions and velocities of bodies. The velocity change is obtained by deriving the expression v=∇v.x, where ∇v is the macroscopic velocity gradient, giving in an incremental form: Δv=Δ ∇v x + ∇v Δx. As a result, velocities are modified as soon as ``velGrad`` changes, according to the first term: Δv(t)=Δ ∇v x(t), while the 2nd term reflects a convective term: Δv'= ∇v v(t-dt/2)."))
+		((bool,velGradChanged,false,Attr::readonly,"true when velGrad has been changed manually (see also :yref:`Cell.nextVelGrad`)")),
 		/*deprec*/
 		((Hsize,hSize,"conform to Yade's names convention.")),
 		/*init*/ ,
@@ -164,6 +170,7 @@
 		.add_property("refSize",&Cell::getRefSize,&Cell::setRefSize,"Reference size of the cell (lengths of initial cell vectors, i.e. column norms of :yref:`hSize<Cell.hSize>`).\n\n.. note:: Modifying this value is deprecated, use :yref:`setBox<Cell.setBox>` instead.\n\n")
 		// useful properties
 		.add_property("trsf",&Cell::getTrsf,&Cell::setTrsf,"Current transformation matrix of the cell, obtained from time integration of :yref:`Cell.velGrad`.")
+		.add_property("velGrad",&Cell::getVelGrad,&Cell::setVelGrad,"Velocity gradient of the transformation; used in :yref:`NewtonIntegrator`. Values of :yref:`velGrad<Cell.velGrad>` accumulate in :yref:`trsf<Cell.trsf>` at every step.\n\n NOTE: changing velGrad at the beginning of a simulation loop would lead to inacurate integration for one step, as it should normaly be changed after the contact laws (but before Newton). To avoid this problem, assignment is deferred automatically. The target value typed in terminal is actually stored in :yref:`Cell.nextVelGrad` and will be applied right in time by Newton integrator.")
 		.def_readonly("size",&Cell::getSize_copy,"Current size of the cell, i.e. lengths of the 3 cell lateral vectors contained in :yref:`Cell.hSize` columns. Updated automatically at every step.")
 		.add_property("volume",&Cell::getVolume,"Current volume of the cell.")
 		// functions

=== modified file 'core/Clump.cpp'
--- core/Clump.cpp	2012-08-01 18:58:16 +0000
+++ core/Clump.cpp	2013-01-31 15:44:02 +0000
@@ -20,15 +20,29 @@
 
 void Clump::add(const shared_ptr<Body>& clumpBody, const shared_ptr<Body>& subBody){
 	Body::id_t subId=subBody->getId();
-	if(subBody->clumpId!=Body::ID_NONE) throw std::invalid_argument(("Body #"+lexical_cast<string>(subId)+" is already in clump #"+lexical_cast<string>(subBody->clumpId)).c_str());
 	const shared_ptr<Clump> clump=YADE_PTR_CAST<Clump>(clumpBody->shape);
 	if(clump->members.count(subId)!=0) throw std::invalid_argument(("Body #"+lexical_cast<string>(subId)+" is already part of this clump #"+lexical_cast<string>(clumpBody->id)).c_str());
-	
-	clump->members[subId]=Se3r(); // meaningful values will be put in by Clump::updateProperties
-	subBody->clumpId=clumpBody->id;
+	if(subBody->isClumpMember()) throw std::invalid_argument(("Body #"+lexical_cast<string>(subId)+" is already a clump member of #"+lexical_cast<string>(subBody->clumpId)).c_str());
+	else if(subBody->isClump()){
+		const shared_ptr<Clump> subClump=YADE_PTR_CAST<Clump>(subBody->shape);
+		FOREACH(const MemberMap::value_type& mm, subClump->members){
+			const Body::id_t& memberId=mm.first;
+			Scene* scene(Omega::instance().getScene().get());	// get scene
+			const shared_ptr<Body>& member=Body::byId(memberId,scene);
+			assert(member->isClumpMember());
+			member->clumpId=clumpBody->id;
+			clump->members[memberId]=Se3r();// meaningful values will be put in by Clump::updateProperties
+			LOG_DEBUG("Added body #"<<memberId->id<<" to clump #"<<clumpBody->id);
+		}
+		LOG_DEBUG("Clump #"<<subClump->id<<" will be erased.");// see addToClump() in yadeWrapper.cpp
+	}
+	else{	// subBody must be a standalone!
+		clump->members[subId]=Se3r();// meaningful values will be put in by Clump::updateProperties
+		subBody->clumpId=clumpBody->id;
+	}
 	clumpBody->clumpId=clumpBody->id; // just to make sure
 	clumpBody->setBounded(false); // disallow collisions with the clump itself
-	LOG_DEBUG("Added body #"<<subBody->id<<" to clump #"<<clumpBody->id);
+	if(subBody->isStandalone()){LOG_DEBUG("Added body #"<<subBody->id<<" to clump #"<<clumpBody->id);}
 }
 
 void Clump::del(const shared_ptr<Body>& clumpBody, const shared_ptr<Body>& subBody){

=== modified file 'core/Clump.hpp'
--- core/Clump.hpp	2012-08-01 18:58:16 +0000
+++ core/Clump.hpp	2013-03-06 17:30:45 +0000
@@ -78,7 +78,7 @@
 				// velocity update
 				subState->vel=clumpState->vel+clumpState->angVel.cross(subState->pos-clumpState->pos);
 				subState->angVel=clumpState->angVel;
-				if(likely(integrator)) integrator->saveMaximaDisplacement(b);
+				if(integrator) integrator->saveMaximaDisplacement(b);
 			}
 		}
 

=== modified file 'core/EnergyTracker.hpp'
--- core/EnergyTracker.hpp	2011-02-15 11:36:29 +0000
+++ core/EnergyTracker.hpp	2013-03-28 12:02:15 +0000
@@ -53,7 +53,7 @@
 	typedef std::map<std::string,int> mapStringInt;
 	typedef std::pair<std::string,int> pairStringInt;
 
-	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(EnergyTracker,Serializable,"Storage for tracing energies. Only to be used if O.traceEnergy is True.",
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(EnergyTracker,Serializable,"Storage for tracing energies. Only to be used if :yref:`O.trackEnergy<Omega.trackEnergy>` is True.",
 		((OpenMPArrayAccumulator<Real>,energies,,,"Energy values, in linear array"))
 		((mapStringInt,names,,Attr::hidden,"Associate textual name to an index in the energies array."))
 		((vector<bool>,resetStep,,Attr::hidden,"Whether the respective energy value should be reset at every step."))

=== modified file 'core/Engine.hpp'
--- core/Engine.hpp	2012-11-27 12:16:34 +0000
+++ core/Engine.hpp	2013-05-14 21:24:11 +0000
@@ -48,9 +48,13 @@
 
 	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Engine,Serializable,"Basic execution unit of simulation, called from the simulation loop (O.engines)",
 		((bool,dead,false,,"If true, this engine will not run at all; can be used for making an engine temporarily deactivated and only resurrect it at a later point."))
-		((int, ompThreads, -1,,"Number of threads to be used in the engine. If ompThreads<0 (default), the number will be typically OMP_NUM_THREADS or the number N defined by 'yade -jN' (this behavior can depend on the engine though). This attribute will only affect engines whose code includes openMP parallel regions (e.g. :yref:`InteractionLoop`). This attribute is mostly usefull for experiments or when combining :yref:`ParallelEngine` with engines that run parallel regions, resulting in nested OMP loops with different number of threads at each level."))
+		((int, ompThreads, -1,,"Number of threads to be used in the engine. If ompThreads<0 (default), the number will be typically OMP_NUM_THREADS or the number N defined by 'yade -jN' (this behavior can depend on the engine though). This attribute will only affect engines whose code includes openMP parallel regions (e.g. :yref:`InteractionLoop`). This attribute is mostly useful for experiments or when combining :yref:`ParallelEngine` with engines that run parallel regions, resulting in nested OMP loops with different number of threads at each level."))
 		((string,label,,,"Textual label for this object; must be valid python identifier, you can refer to it directly from python.")),
-		/* ctor */ scene=Omega::instance().getScene().get() ,
+		/* ctor */ scene=Omega::instance().getScene().get();
+		#ifdef USE_TIMING_DELTAS
+			timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas);
+		#endif
+		,
 		/* py */
 		.add_property("execTime",&Engine::timingInfo_nsec_get,&Engine::timingInfo_nsec_set,"Cummulative time this Engine took to run (only used if :yref:`O.timingEnabled<Omega.timingEnabled>`\\ ==\\ ``True``).")
 		.add_property("execCount",&Engine::timingInfo_nExec_get,&Engine::timingInfo_nExec_set,"Cummulative count this engine was run (only used if :yref:`O.timingEnabled<Omega.timingEnabled>`\\ ==\\ ``True``).")

=== modified file 'core/Functor.hpp'
--- core/Functor.hpp	2011-01-09 16:34:50 +0000
+++ core/Functor.hpp	2013-04-23 14:07:34 +0000
@@ -12,6 +12,7 @@
 
 #include<yade/lib/serialization/Serializable.hpp>
 #include<yade/lib/multimethods/FunctorWrapper.hpp>
+#include<yade/core/Timing.hpp>
 
 class TimingDeltas;
 class Scene;
@@ -25,7 +26,11 @@
 	virtual ~Functor(); // defined in Dispatcher.cpp
 	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Functor,Serializable,"Function-like object that is called by Dispatcher, if types of arguments match those the Functor declares to accept.",
 		((string,label,,,"Textual label for this object; must be valid python identifier, you can refer to it directly fron python (must be a valid python identifier).")),
-		/*ctor*/,
+		/*ctor*/
+		#ifdef USE_TIMING_DELTAS
+			timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas);
+		#endif
+		,
 		.def_readonly("timingDeltas",&Functor::timingDeltas,"Detailed information about timing inside the Dispatcher itself. Empty unless enabled in the source code and O.timingEnabled==True.")
 		.add_property("bases",&Functor::getFunctorTypes,"Ordered list of types (as strings) this functor accepts.")
 	);	

=== modified file 'core/InteractionContainer.cpp'
--- core/InteractionContainer.cpp	2012-09-21 19:03:18 +0000
+++ core/InteractionContainer.cpp	2013-03-06 17:30:45 +0000
@@ -22,8 +22,11 @@
 	assert((Body::id_t)bodies->size()>id1); // the bodies must exist already
 	assert((Body::id_t)bodies->size()>id2); 
 	
-	const shared_ptr<Body>& b1=(*bodies)[id1]; // body with the smaller id will hold the pointer
+	const shared_ptr<Body>& b1=(*bodies)[id1];
+	const shared_ptr<Body>& b2=(*bodies)[id2];
+	
 	if(!b1->intrs.insert(Body::MapId2IntrT::value_type(id2,i)).second) return false; // already exists
+	if(!b2->intrs.insert(Body::MapId2IntrT::value_type(id1,i)).second) return false; 
 	
 	linIntrs.resize(++currSize); // currSize updated
 	linIntrs[currSize-1]=i; // assign last element
@@ -53,12 +56,13 @@
 	assert(bodies);
 	boost::mutex::scoped_lock lock(drawloopmutex);
 	if (id1>id2) swap(id1,id2);
-	if(unlikely(id2>=(Body::id_t)bodies->size())) return false; // no such interaction
+	if(id2>=(Body::id_t)bodies->size()) return false; // no such interaction
 	
 	const shared_ptr<Body>& b1((*bodies)[id1]);
+	const shared_ptr<Body>& b2((*bodies)[id2]);
 	
 	int linIx=-1;
-	if(unlikely(!b1)) linIx=linPos;
+	if(!b1) linIx=linPos;
 	else {
 		Body::MapId2IntrT::iterator I(b1->intrs.find(id2));
 		if(I==b1->intrs.end()) linIx=linPos;
@@ -67,7 +71,13 @@
 			assert(linIx==linPos);
 			//erase from body, we also erase from linIntrs below
 			b1->intrs.erase(I);
+			if (b2) { 
+				Body::MapId2IntrT::iterator I2(b2->intrs.find(id1));
+				if (not(I2==b2->intrs.end())) { 
+					b2->intrs.erase(I2); 
+				}
 			}
+		}
 	}
 	if(linIx<0) {
 		LOG_ERROR("InteractionContainer::erase: attempt to delete interaction with a deleted body (the definition of linPos in the call to erase() should fix the problem) for  ##"+lexical_cast<string>(id1)+"+"+lexical_cast<string>(id2));
@@ -87,9 +97,9 @@
 	assert(bodies);
 	if (id1>id2) swap(id1,id2); 
 	// those checks could be perhaps asserts, but pyInteractionContainer has no access to the body container...
-	if(unlikely(id2>=(Body::id_t)bodies->size())){ empty=shared_ptr<Interaction>(); return empty; }
+	if(id2>=(Body::id_t)bodies->size()){ empty=shared_ptr<Interaction>(); return empty; }
 	const shared_ptr<Body>& b1((*bodies)[id1]);
-	if(unlikely(!b1)) { empty=shared_ptr<Interaction>(); return empty; }
+	if(!b1) { empty=shared_ptr<Interaction>(); return empty; }
 	Body::MapId2IntrT::iterator I(b1->intrs.find(id2));
 	if (I!=b1->intrs.end()) return I->second;
 	else { empty=shared_ptr<Interaction>(); return empty; }
@@ -107,7 +117,7 @@
 
 
 void InteractionContainer::requestErase(Body::id_t id1, Body::id_t id2, bool force){
-	const shared_ptr<Interaction> I=find(id1,id2); if(unlikely(!I)) return;
+	const shared_ptr<Interaction> I=find(id1,id2); if(!I) return;
 	I->reset(); IdsForce v={id1,id2,force};
 	#ifdef YADE_OPENMP
 		threadsPendingErase[omp_get_thread_num()].push_back(v);

=== modified file 'core/Scene.cpp'
--- core/Scene.cpp	2012-02-17 07:11:54 +0000
+++ core/Scene.cpp	2013-03-07 18:28:01 +0000
@@ -82,7 +82,7 @@
 		// hopefully this will not break in some margin cases (subStepping with setting _nextEngines and such)
 		subStep=-1;
 	}
-	if(likely(!subStepping && subStep<0)){
+	if(!subStepping && subStep<0){
 		/* set substep to 0 during the loop, so that engines/nextEngines handler know whether we are inside the loop currently */
 		subStep=0;
 		// ** 1. ** prologue
@@ -93,9 +93,9 @@
 		// ** 2. ** engines
 		FOREACH(const shared_ptr<Engine>& e, engines){
 			e->scene=this;
-			if(unlikely(e->dead || !e->isActivated())) continue;
+			if(e->dead || !e->isActivated()) continue;
 			e->action();
-			if(unlikely(TimingInfo_enabled)) {TimingInfo::delta now=TimingInfo::getNow(); e->timingInfo.nsec+=now-last; e->timingInfo.nExec+=1; last=now;}
+			if(TimingInfo_enabled) {TimingInfo::delta now=TimingInfo::getNow(); e->timingInfo.nsec+=now-last; e->timingInfo.nExec+=1; last=now;}
 		}
 		// ** 3. ** epilogue
 				// Calculation speed
@@ -202,9 +202,10 @@
 				if(!isinf(b->bound->min[i])) mn[i]=min(mn[i],b->bound->min[i]);
 			}
 		} else {
-	 		mx=mx.cwise().max(b->state->pos);
- 			mn=mn.cwise().min(b->state->pos);
+	 		mx=mx.cwiseMax(b->state->pos);
+ 			mn=mn.cwiseMin(b->state->pos);
 		}
 	}
-	bound->min=mn; bound->max=mx;
+	bound->min=mn; 
+  bound->max=mx;
 }

=== modified file 'core/State.hpp'
--- core/State.hpp	2012-08-23 14:19:01 +0000
+++ core/State.hpp	2013-02-26 10:56:01 +0000
@@ -72,7 +72,7 @@
 		// references must be set using wrapper funcs
 		.add_property("pos",&State::pos_get,&State::pos_set,"Current position.")
 		.add_property("ori",&State::ori_get,&State::ori_set,"Current orientation.")
-		.def("displ",&State::displ,"Displacement from :yref:`reference position<State.refPos>` (:yref:`pos<State.pos>` - :yref:`refPos<State.refPos>`")
+		.def("displ",&State::displ,"Displacement from :yref:`reference position<State.refPos>` (:yref:`pos<State.pos>` - :yref:`refPos<State.refPos>`)")
 		.def("rot",&State::rot,"Rotation from :yref:`reference orientation<State.refPos>` (as rotation vector)")
 	);
 	REGISTER_INDEX_COUNTER(State);

=== modified file 'core/main/main.py.in'
--- core/main/main.py.in	2012-11-25 13:16:24 +0000
+++ core/main/main.py.in	2013-05-07 09:21:35 +0000
@@ -3,10 +3,15 @@
 # syntax:python
 
 import sys,os,os.path,time
+try:
+	import _io
+except ImportError:
+	import io
+
 # get yade path (allow YADE_PREFIX to override)
 prefix,suffix='${runtimePREFIX}' if not os.environ.has_key('YADE_PREFIX') else os.environ['YADE_PREFIX'],'${SUFFIX}'
 # duplicate some items from yade.config here, so that we can increase verbosity when the c++ part is booting
-features,version='${features}'.split(','),'${realVersion}'
+features,version='${features}'.split(' '),'${realVersion}'
 
 libPATH='${LIBRARY_OUTPUT_PATH}'
 if (libPATH[1:] == '{LIBRARY_OUTPUT_PATH}'): libPATH='lib'
@@ -17,22 +22,46 @@
 	raise RuntimeError('Libraries are not found! ('+libDir+'/py/yade/__init__.py, /py/yade/__init__.py)')
 
 
+
+
 # handle command-line options first
-import optparse
-par=optparse.OptionParser(usage='%prog [options] [ simulation.xml[.bz2] | script.py [script options]]',prog=os.path.basename(sys.argv[0]),version='%s (%s)'%(version,','.join(features)),description="Yade: open-source platform for dynamic compuations. Homepage http://www.yade-dem.org, code hosted at http://www.launchpad.net/yade. This is version %s (with features %s)."%(version,','.join(features)))
-par.add_option('-j','--threads',help='Number of OpenMP threads to run; defaults to 1. Equivalent to setting OMP_NUM_THREADS environment variable.',dest='threads',type='int')
-par.add_option('--cores',help='Set number of OpenMP threads (as \-\-threads) and in addition set affinity of threads to the cores given.',dest='cores',type='string')
-par.add_option('--update',help='Update deprecated class names in given script(s) using text search & replace. Changed files will be backed up with ~ suffix. Exit when done without running any simulation.',dest='updateScripts',action='store_true')
-par.add_option('--nice',help='Increase nice level (i.e. decrease priority) by given number.',dest='nice',type='int')
-par.add_option('-x',help='Exit when the script finishes',dest='exitAfter',action='store_true')
-par.add_option('-n',help="Run without graphical interface (equivalent to unsetting the DISPLAY environment variable)",dest='nogui',action='store_true')
-par.add_option('--generate-manpage',help="Generate man page documenting this program and exit",dest='manpage',metavar='FILE')
-par.add_option('--test',help="Run regression test suite and exit; the exists status is 0 if all tests pass, 1 if a test fails and 2 for an unspecified exception.",dest="test",action='store_true')
-par.add_option('--checks',help='Run a series of user-defined check tests as described in ${sourceRoot}/scripts/checks-and-tests/checks/README',dest='checks',action='store_true')
-par.add_option('--performance',help='Starts a test to measure the productivity',dest='performance',action='store_true')
-par.disable_interspersed_args()
-
-opts,args=par.parse_args()
+try:
+	import argparse
+except ImportError: # argparse not present, print error message
+	raise RuntimeError("\n\nPlease install 'python-argparse' package.\n")
+prog = os.path.basename(sys.argv[0])
+par=argparse.ArgumentParser(usage='%s [options] [ simulation.xml[.bz2] | script.py [script options]]'%prog,
+  prog=prog,description="Yade: open-source platform for dynamic compuations. It\
+  is an extensible open-source framework for discrete numerical models, focused\
+  on Discrete Element Method. The computation parts are written in c++ using\
+  flexible object model, allowing independent implementation of new algorithms\
+  and interfaces. Python is used for rapid and concise scene construction, \
+  simulation control, postprocessing and debugging.\
+  Available features: %s.\
+  Homepage http://www.yade-dem.org, code hosted at http://www.launchpad.net/yade."%features
+  )
+par.add_argument('-v','--version',help='Print version and exit.',dest='version',action='store_true')
+par.add_argument('-j','--threads',help='Number of OpenMP threads to run; defaults to 1. Equivalent to setting OMP_NUM_THREADS environment variable.',dest='threads',type=int)
+par.add_argument('--cores',help='Set number of OpenMP threads (as \-\-threads) and in addition set affinity of threads to the cores given.',dest='cores',type=str)
+par.add_argument('--update',help='Update deprecated class names in given script(s) using text search & replace. Changed files will be backed up with ~ suffix. Exit when done without running any simulation.',dest='updateScripts',nargs='+')
+par.add_argument('--nice',help='Increase nice level (i.e. decrease priority) by given number.',dest='nice',type=int)
+par.add_argument('-x',help='Exit when the script finishes',dest='exitAfter',action='store_true')
+par.add_argument('-n',help="Run without graphical interface (equivalent to unsetting the DISPLAY environment variable)",dest='nogui',action='store_true')
+par.add_argument('--test',help="Run regression test suite and exit; the exists status is 0 if all tests pass, 1 if a test fails and 2 for an unspecified exception.",dest="test",action='store_true')
+par.add_argument('--checks',help='Run a series of user-defined check tests as described in /yade/scripts/checks-and-tests/checks/README',dest='checks',action='store_true')
+par.add_argument('--performance',help='Starts a test to measure the productivity',dest='performance',action='store_true')
+par.add_argument('script',nargs='?',default='',type=str,help=argparse.SUPPRESS)
+par.add_argument('args',nargs=argparse.REMAINDER,help=argparse.SUPPRESS) # see argparse doc, par.disable_interspersed_args() from optargs module
+opts=par.parse_args()
+args = opts.args
+
+if opts.version:
+	print 'Yade version: %s'%version
+	sys.exit(0)
+
+if opts.script:
+	args.insert(0,opts.script) # for compatibility with userSession(), could be modified in the future
+
 
 ## remove later
 ## python2.5 relative module imports workaround
@@ -79,7 +108,8 @@
 elif opts.threads: os.environ['OMP_NUM_THREADS']=str(opts.threads)
 else: os.environ['OMP_NUM_THREADS']='1'
 
-sys.stderr.write('Welcome to Yade '+version+'\n')
+if __name__ == "__main__": # do not print this while importing yade in other python application
+	sys.stderr.write('Welcome to Yade '+version+'\n')
 
 # initialization and c++ plugins import
 import yade
@@ -94,14 +124,6 @@
 if opts.updateScripts:
 	yade.system.updateScripts(args)
 	sys.exit(0)
-if opts.manpage:
-	import yade.manpage
-	yade.manpage.generate_manpage(par,yade.config.metadata,opts.manpage,section=1,seealso='yade%s-batch (1)'%suffix)
-	print 'Manual page %s generated.'%opts.manpage
-	sys.exit(0)
-if opts.nice:
-	os.nice(opts.nice)
-	yade.wrapper.Omega().disableGdb()
 
 # modify sys.argv in-place so that it can be handled by userSession
 sys.argv=yade.runtime.argv=args
@@ -126,6 +148,8 @@
 	# prepare nice namespace for users
 	import yade.runtime
 	import sys
+	if __name__ != "__main__": # for importing as python module
+		return
 	# start non-blocking qt4 app here; need to ask on the mailing list on how to make it functional
 	## with ipython 0.11, start the even loop early (impossible with 0.10, which is thread-based)
 	#if qt4 and yade.runtime.ipython_version==11:
@@ -151,7 +175,7 @@
 			runScript(arg0)
 	if yade.runtime.opts.exitAfter: sys.exit(0)
 	# common ipython configuration
-	banner='[[ ^L clears screen, ^U kills line. '+', '.join((['F12 controller','F11 3d view','F10 both','F9 generator'] if (qt4) else [])+['F8 plot'])+'. ]]'
+	banner='[[ ^L clears screen, ^U kills line. '+', '.join((['F12 controller','F11 3d view (use h-key for showing help)','F10 both','F9 generator'] if (qt4) else [])+['F8 plot'])+'. ]]'
 	ipconfig=dict( # ipython options, see e.g. http://www.cv.nrao.edu/~rreid/casa/tips/ipy_user_conf.py
 		prompt_in1='Yade [\#]: ',
 		prompt_in2='     .\D.: ',
@@ -219,10 +243,11 @@
 		# let's just pretend any exception means the display would not work
 		gui=None
 
-# run remote access things, before actually starting the user session
-from yade import remote
-yade.remote.useQThread=(gui=='qt4')
-yade.remote.runServers()
+# run remote access things, before actually starting the user session (not while imported by other python application)
+if __name__ == "__main__":
+	from yade import remote
+	yade.remote.useQThread=(gui=='qt4')
+	yade.remote.runServers()
 
 if gui==None:
 	userSession()
@@ -236,4 +261,5 @@
 	qapp=QtGui.QApplication(sys.argv)
 	userSession(qt4=True,qapp=qapp)
 
-O.exitNoBacktrace()
+if __name__ == "__main__":
+	O.exitNoBacktrace()

=== modified file 'core/main/yade-batch.in'
--- core/main/yade-batch.in	2012-10-30 17:22:52 +0000
+++ core/main/yade-batch.in	2013-03-26 19:21:11 +0000
@@ -328,7 +328,12 @@
 		sys.stdout.flush()
 
 
-import sys,re,optparse,os
+import sys,re,os
+try:
+	import argparse
+except ImportError: # argparse not present, print error message
+	raise RuntimeError("\n\nPlease install 'python-argparse' package.\n")
+
 def getNumCores():
 	nCpu=1
 	try:
@@ -341,38 +346,38 @@
 	return nCpu
 numCores=getNumCores()
 maxOmpThreads=numCores if 'openmp' in yade.config.features else 1
-
-parser=optparse.OptionParser(usage='%prog [options] [ TABLE [SIMULATION.py] | SIMULATION.py[/nCores] [...] ]',description='%prog runs yade simulation multiple times with different parameters.\n\nSee https://yade-dem.org/sphinx/user.html#batch-queuing-and-execution-yade-batch for details.\n\nBatch can be specified either with parameter table TABLE (must not end in .py), which is either followed by exactly one SIMULATION.py (must end in .py), or contains !SCRIPT column specifying the simulation to be run. The second option is to specify multiple scripts, which can optionally have /nCores suffix to specify number of cores for that particular simulation (corresponds to !THREADS column in the parameter table), e.g. sim.py/3.')
-parser.add_option('-j','--jobs',dest='maxJobs',type='int',help="Maximum number of simultaneous threads to run (default: number of cores, further limited by OMP_NUM_THREADS if set by the environment: %d)"%numCores,metavar='NUM',default=numCores)
-parser.add_option('--job-threads',dest='defaultThreads',type='int',help="Default number of threads for one job; can be overridden by per-job with !THREADS (or !OMP_NUM_THREADS) column. Defaults to 1.",metavar='NUM',default=1)
-parser.add_option('--force-threads',action='store_true',dest='forceThreads',help='Force jobs to not use more cores than the maximum (see \-j), even if !THREADS colums specifies more.')
-parser.add_option('--log',dest='logFormat',help='Format of job log files: must contain a $, % or @, which will be replaced by script name, line number or by description column respectively (default: $.@.log)',metavar='FORMAT',default='$.@.log')
-parser.add_option('--global-log',dest='globalLog',help='Filename where to redirect output of yade-batch itself (as opposed to \-\-log); if not specified (default), stdout/stderr are used',metavar='FILE')
-parser.add_option('-l','--lines',dest='lineList',help='Lines of TABLE to use, in the format 2,3-5,8,11-13 (default: all available lines in TABLE)',metavar='LIST')
-parser.add_option('--nice',dest='nice',type='int',help='Nice value of spawned jobs (default: 10)',default=10)
-parser.add_option('--cpu-affinity',dest='affinity',action='store_true',help='Bind each job to specific CPU cores; cores are assigned in a quasi-random order, depending on availability at the moment the jobs is started. Each job can override this setting by setting AFFINE column.')
-parser.add_option('--executable',dest='executable',help='Name of the program to run (default: %s). Jobs can override with !EXEC column.'%executable,default=executable,metavar='FILE')
-parser.add_option('--debug',dest='debug',action='store_true',help='Run the executable with \-\-debug. Can be overriddenn per-job with !DEBUG column.',default=False)
-parser.add_option('--gnuplot',dest='gnuplotOut',help='Gnuplot file where gnuplot from all jobs should be put together',default=None,metavar='FILE')
-parser.add_option('--dry-run',action='store_true',dest='dryRun',help='Do not actually run (useful for getting gnuplot only, for instance)',default=False)
-parser.add_option('--http-wait',action='store_true',dest='httpWait',help='Do not quit if still serving overview over http repeatedly',default=False)
-parser.add_option('--generate-manpage',help='Generate man page documenting this program and exit',dest='manpage',metavar='FILE')
-parser.add_option('--plot-update',type='int',dest='plotAlwaysUpdateTime',help='Interval (in seconds) at which job plots will be updated even if not requested via HTTP. Non-positive values will make the plots not being updated and saved unless requested via HTTP (see \-\-plot-timeout for controlling maximum age of those).  Plots are saved at exit under the same name as the log file, with the .log extension removed. (default: 120 seconds)',metavar='TIME',default=120)
-parser.add_option('--plot-timeout',type='int',dest='plotTimeout',help='Maximum age (in seconds) of plots served over HTTP; they will be updated if they are older. (default: 30 seconds)',metavar='TIME',default=30)
-parser.add_option('--refresh',type='int',dest='refresh',help='Refresh rate of automatically reloaded web pages (summary, logs, ...).',metavar='TIME',default=30)
-parser.add_option('--timing',type='int',dest='timing',default=0,metavar='COUNT',help='Repeat each job COUNT times, and output a simple table with average/variance/minimum/maximum job duration; used for measuring how various parameters affect execution time. Jobs can override the global value with the !COUNT column.')
-parser.add_option('--timing-output',type='str',metavar='FILE',dest='timingOut',default=None,help='With \-\-timing, save measured durations to FILE, instead of writing to standard output.')
-parser.add_option('--randomize',action='store_true',dest='randomize',help='Randomize job order (within constraints given by assigned cores).')
-#parser.add_option('--serial',action='store_true',dest='serial',default=False,help='Run all jobs serially, even if there are free cores
-opts,args=parser.parse_args()
+features,version='${features}'.split(','),'${realVersion}'
+
+prog = os.path.basename(sys.argv[0])
+parser=argparse.ArgumentParser(usage='%s [options] [ TABLE [SIMULATION.py] | SIMULATION.py[/nCores] [...] ]'%prog,description='%s runs yade simulation multiple times with different parameters.\n\nSee https://yade-dem.org/sphinx/user.html#batch-queuing-and-execution-yade-batch for details.\n\nBatch can be specified either with parameter table TABLE (must not end in .py), which is either followed by exactly one SIMULATION.py (must end in .py), or contains !SCRIPT column specifying the simulation to be run. The second option is to specify multiple scripts, which can optionally have /nCores suffix to specify number of cores for that particular simulation (corresponds to !THREADS column in the parameter table), e.g. sim.py/3.'%prog)
+parser.add_argument('-j','--jobs',dest='maxJobs',type=int,help="Maximum number of simultaneous threads to run (default: number of cores, further limited by OMP_NUM_THREADS if set by the environment: %d)"%numCores,metavar='NUM',default=numCores)
+parser.add_argument('-v','--version',help='Print version and exit.',dest='version',action='store_true')
+parser.add_argument('--job-threads',dest='defaultThreads',type=int,help="Default number of threads for one job; can be overridden by per-job with !THREADS (or !OMP_NUM_THREADS) column. Defaults to 1.",metavar='NUM',default=1)
+parser.add_argument('--force-threads',action='store_true',dest='forceThreads',help='Force jobs to not use more cores than the maximum (see \-j), even if !THREADS colums specifies more.')
+parser.add_argument('--log',dest='logFormat',help='Format of job log files: must contain a $, %% or @, which will be replaced by script name, line number or by description column respectively (default: $.@.log)',metavar='FORMAT',default='$.@.log')
+parser.add_argument('--global-log',dest='globalLog',help='Filename where to redirect output of yade-batch itself (as opposed to \-\-log); if not specified (default), stdout/stderr are used',metavar='FILE')
+parser.add_argument('-l','--lines',dest='lineList',help='Lines of TABLE to use, in the format 2,3-5,8,11-13 (default: all available lines in TABLE)',metavar='LIST')
+parser.add_argument('--nice',dest='nice',type=int,help='Nice value of spawned jobs (default: 10)',default=10)
+parser.add_argument('--cpu-affinity',dest='affinity',action='store_true',help='Bind each job to specific CPU cores; cores are assigned in a quasi-random order, depending on availability at the moment the jobs is started. Each job can override this setting by setting AFFINE column.')
+parser.add_argument('--executable',dest='executable',help='Name of the program to run (default: %s). Jobs can override with !EXEC column.'%executable,default=executable,metavar='FILE')
+parser.add_argument('--gnuplot',dest='gnuplotOut',help='Gnuplot file where gnuplot from all jobs should be put together',default=None,metavar='FILE')
+parser.add_argument('--dry-run',action='store_true',dest='dryRun',help='Do not actually run (useful for getting gnuplot only, for instance)',default=False)
+parser.add_argument('--http-wait',action='store_true',dest='httpWait',help='Do not quit if still serving overview over http repeatedly',default=False)
+parser.add_argument('--plot-update',type=int,dest='plotAlwaysUpdateTime',help='Interval (in seconds) at which job plots will be updated even if not requested via HTTP. Non-positive values will make the plots not being updated and saved unless requested via HTTP (see \-\-plot-timeout for controlling maximum age of those).  Plots are saved at exit under the same name as the log file, with the .log extension removed. (default: 120 seconds)',metavar='TIME',default=120)
+parser.add_argument('--plot-timeout',type=int,dest='plotTimeout',help='Maximum age (in seconds) of plots served over HTTP; they will be updated if they are older. (default: 30 seconds)',metavar='TIME',default=30)
+parser.add_argument('--refresh',type=int,dest='refresh',help='Refresh rate of automatically reloaded web pages (summary, logs, ...).',metavar='TIME',default=30)
+parser.add_argument('--timing',type=int,dest='timing',default=0,metavar='COUNT',help='Repeat each job COUNT times, and output a simple table with average/variance/minimum/maximum job duration; used for measuring how various parameters affect execution time. Jobs can override the global value with the !COUNT column.')
+parser.add_argument('--timing-output',type=str,metavar='FILE',dest='timingOut',default=None,help='With \-\-timing, save measured durations to FILE, instead of writing to standard output.')
+parser.add_argument('--randomize',action='store_true',dest='randomize',help='Randomize job order (within constraints given by assigned cores).')
+parser.add_argument('args',nargs=argparse.REMAINDER,help=argparse.SUPPRESS) # see argparse doc, par.disable_interspersed_args() from optargs module
+#parser.add_argument('--serial',action='store_true',dest='serial',default=False,help='Run all jobs serially, even if there are free cores
+opts=parser.parse_args()
+args = opts.args
+
 logFormat,lineList,maxJobs,nice,executable,gnuplotOut,dryRun,httpWait,globalLog=opts.logFormat,opts.lineList,opts.maxJobs,opts.nice,opts.executable,opts.gnuplotOut,opts.dryRun,opts.httpWait,opts.globalLog
 
-if opts.manpage:
-	import yade.manpage
-	yade.config.metadata['short_desc']='batch system for computational platform Yade'
-	yade.config.metadata['long_desc']='Manage batches of computation jobs for the Yade platform; batches are described using text-file tables with parameters which are passed to individual runs of yade. Jobs are being run with pre-defined number of computational cores as soon as the required number of cores is available. Logs of all computations are stored in files and the batch progress can be watched online at (usually) http://localhost:9080. Unless overridden, the executable yade%s is used to run jobs.'%(suffix)
-	yade.manpage.generate_manpage(parser,yade.config.metadata,opts.manpage,section=1,seealso='yade%s (1)\n.br\nhttps://yade-dem.org/sphinx/user.html#batch-queuing-and-execution-yade-batch'%suffix)
-	print 'Manual page %s generated.'%opts.manpage
+if opts.version:
+	print 'Yade version: %s, features: %s'%(version,','.join(features))
 	sys.exit(0)
 
 if globalLog:
@@ -436,7 +441,6 @@
 	nCores=opts.defaultThreads
 	jobExecutable=executable
 	jobAffinity=opts.affinity
-	jobDebug=opts.debug
 	jobCount=opts.timing
 	for col in params[l].keys():
 		if col[0]!='!': continue
@@ -445,7 +449,6 @@
 		elif col=='!EXEC': jobExecutable=val
 		elif col=='!SCRIPT': script=val
 		elif col=='!AFFINITY': jobAffinity=eval(val)
-		elif col=='!DEBUG': jobDebug=eval(val)
 		elif col=='!COUNT': jobCount=eval(val)
 		else: envVars+=['%s=%s'%(head[1:],values[l][col])]
 	if not script:
@@ -477,7 +480,7 @@
 		env='YADE_BATCH='
 		if table: env+='<a href="jobs/%d/table">%s:%d</a>'%(jobNum,table,l) # keep YADE_BATCH empty (but still defined) if running a single simulation
 		env+=' DISPLAY= %s '%(' '.join(envVars))
-		cmd='%s%s [threadspec] %s -x <a href="jobs/%d/script">%s</a>'%(jobExecutable,' --debug' if jobDebug else '','--nice=%s'%nice if nice!=None else '',i,script)
+		cmd='%s%s [threadspec] %s -x <a href="jobs/%d/script">%s</a>'%(jobExecutable,'','--nice=%s'%nice if nice!=None else '',i,script)
 		log='> <a href="jobs/%d/log">%s</a> 2>&1'%(jobNum,pipes.quote(logFile2))
 		hrefCmd=env+cmd+log
 		fullCmd=re.sub('(<a href="[^">]+">|</a>)','',hrefCmd)

=== modified file 'doc/sphinx/conf.py'
--- doc/sphinx/conf.py	2012-10-31 18:43:29 +0000
+++ doc/sphinx/conf.py	2013-03-21 19:28:57 +0000
@@ -21,12 +21,11 @@
 ##
 ## http://docutils.sourceforge.net/docs/howto/rst-roles.html
 
-import sys
+import sys, os, re
 from docutils import nodes
 from sphinx import addnodes
 from sphinx.roles import XRefRole
 import docutils
-import re
 
 #
 # needed for creating hyperlink targets.
@@ -40,6 +39,7 @@
 import __builtin__
 if 'latex' in sys.argv: __builtin__.writer='latex'
 elif 'html' in sys.argv: __builtin__.writer='html'
+elif 'epub' in sys.argv: __builtin__.writer='epub'
 else: raise RuntimeError("Must have either 'latex' or 'html' on the command line (hack for reference styles)")
 
 
@@ -140,11 +140,13 @@
 .. |ystatic| replace:: *(static)*
 """
 
-
+import collections
 def customExclude(app, what, name, obj, skip, options):
 	if name=='clone':
 		if 'Serializable.clone' in str(obj): return False
 		return True
+	#escape crash on non iterable __doc__ in some qt object
+	if hasattr(obj,'__doc__') and obj.__doc__ and not isinstance(obj.__doc__, collections.Iterable): return True
 	if hasattr(obj,'__doc__') and obj.__doc__ and ('|ydeprecated|' in obj.__doc__ or '|yhidden|' in obj.__doc__): return True
 	#if re.match(r'\b(__init__|__reduce__|__repr__|__str__)\b',name): return True
 	if name.startswith('_'):
@@ -360,7 +362,18 @@
 	if yade.runtime.ipython_version<12:
 		import ipython_directive as id
 	else:
-		import ipython_directive012 as id
+		if 12<=yade.runtime.ipython_version<13:
+			import ipython_directive012 as id
+		else:
+			import ipython_directive013 as id
+
+	#The next four lines are for compatibility with IPython 0.13.1
+	ipython_rgxin =re.compile(r'(?:In |Yade )\[(\d+)\]:\s?(.*)\s*')
+	ipython_rgxout=re.compile(r'(?:Out| ->  )\[(\d+)\]:\s?(.*)\s*')
+	ipython_promptin ='Yade [%d]:'
+	ipython_promptout=' ->  [%d]: '
+	ipython_cont_spaces='     '
+	#For IPython <=0.12, the following lines are used
 	id.rgxin =re.compile(r'(?:In |Yade )\[(\d+)\]:\s?(.*)\s*')
 	id.rgxout=re.compile(r'(?:Out| ->  )\[(\d+)\]:\s?(.*)\s*')
 	id.rgxcont=re.compile(r'(?:   +)\.\.+:\s?(.*)\s*')
@@ -392,10 +405,15 @@
 		'youtube',
 		'sphinx.ext.todo',
 		]
+
+
 if yade.runtime.ipython_version<12:
 	extensions.append('ipython_directive')
 else:
-	extensions.append('ipython_directive012')
+	if 12<=yade.runtime.ipython_version<13:
+		extensions.append('ipython_directive012')
+	else:
+		extensions.append('ipython_directive013')
 
 # the sidebar extension
 if False:

=== removed file 'doc/sphinx/external.rst'
--- doc/sphinx/external.rst	2010-05-17 08:51:45 +0000
+++ doc/sphinx/external.rst	1970-01-01 00:00:00 +0000
@@ -1,25 +0,0 @@
-External modules
-=================
-
-.. _yade.math
-
-miniEigen (math) module
---------------------------
-
-.. automodule:: miniEigen
-	:members:
-	:undoc-members:
-
-
-.. _gts
-
-gts (GNU Triangulated surface) module
---------------------------------------
-
-.. automodule:: gts
-	:members:
-	:undoc-members:
-	:show-inheritance:
-
-
-

=== modified file 'doc/sphinx/fig/dispatch-loop.svg'
--- doc/sphinx/fig/dispatch-loop.svg	2010-05-17 08:51:45 +0000
+++ doc/sphinx/fig/dispatch-loop.svg	2013-04-24 19:49:00 +0000
@@ -14,7 +14,7 @@
    id="svg2"
    inkscape:label="Pozadí"
    version="1.1"
-   inkscape:version="0.47pre4 r22446"
+   inkscape:version="0.48.3.1 r9886"
    sodipodi:docname="dispatch-loop.svg">
   <defs
      id="defs3">
@@ -75,16 +75,16 @@
      borderopacity="1.0"
      inkscape:pageopacity="0.0"
      inkscape:pageshadow="2"
-     inkscape:zoom="1.979899"
-     inkscape:cx="217.86473"
-     inkscape:cy="22.154429"
+     inkscape:zoom="3.959798"
+     inkscape:cx="178.77018"
+     inkscape:cy="36.389346"
      inkscape:document-units="px"
      inkscape:current-layer="layer1"
-     showgrid="false"
+     showgrid="true"
      inkscape:window-width="1920"
-     inkscape:window-height="1126"
+     inkscape:window-height="1176"
      inkscape:window-x="0"
-     inkscape:window-y="25"
+     inkscape:window-y="24"
      inkscape:window-maximized="1" />
   <metadata
      id="metadata6">
@@ -94,7 +94,7 @@
         <dc:format>image/svg+xml</dc:format>
         <dc:type
            rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
-        <dc:title></dc:title>
+        <dc:title />
       </cc:Work>
     </rdf:RDF>
   </metadata>
@@ -153,25 +153,34 @@
        d="m 144.6741,34.3507 72.2864,6.121424"
        id="path2831"
        inkscape:connector-type="polyline"
-       sodipodi:nodetypes="cc" />
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0" />
     <path
        style="fill:none;stroke:#000000;stroke-width:0.96579325px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
        d="m 141.90933,51.57065 74.7855,-9.125578"
        id="path2833"
        inkscape:connector-type="polyline"
-       sodipodi:nodetypes="cc" />
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0" />
+    <rect
+       style="fill:#8800aa;fill-opacity:0.34181818;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.35636363;stroke-dasharray:none"
+       id="rect3832"
+       width="94.701797"
+       height="22.728432"
+       x="234.35539"
+       y="31.097958" />
     <flowRoot
        xml:space="preserve"
        id="flowRoot2837"
        style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       transform="translate(62.124381,-4.7982246)"><flowRegion
+       transform="translate(82.481524,-4.7982246)"><flowRegion
          id="flowRegion2839"><rect
            id="rect2841"
            width="95.459412"
            height="20.455587"
            x="173.4937"
            y="39.431717" /></flowRegion><flowPara
-         id="flowPara2843">Dem3DofGeom</flowPara><flowPara
+         id="flowPara2843">ScGeom</flowPara><flowPara
          id="flowPara2845" /></flowRoot>    <rect
        style="fill:#5555ff;fill-opacity:0.34181818;stroke:#000000;stroke-opacity:0.46545458"
        id="rect3649"
@@ -195,7 +204,8 @@
        d="M 153.79573,80.847971 227.28432,71.50406"
        id="path2855"
        inkscape:connector-type="polyline"
-       sodipodi:nodetypes="cc" />
+       sodipodi:nodetypes="cc"
+       inkscape:connector-curvature="0" />
     <flowRoot
        xml:space="preserve"
        id="flowRoot2857"
@@ -234,38 +244,38 @@
          id="flowPara3647-7">Material</flowPara></flowRoot>    <text
        xml:space="preserve"
        style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="148.87294"
-       y="17.31669"
+       x="156.61877"
+       y="17.649073"
        id="text3682"
        sodipodi:linespacing="100%"
        transform="matrix(0.99541901,0.09560851,-0.09560851,0.99541901,0,0)"><tspan
          sodipodi:role="line"
          id="tspan3684"
-         x="148.87294"
-         y="17.31669">Ig2_Sphere_Sphere_Dem3DofGeom</tspan></text>
+         x="156.61877"
+         y="17.649073">Ig2_Sphere_Sphere_ScGeom</tspan></text>
     <text
        xml:space="preserve"
        style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="140.26605"
-       y="75.324471"
+       x="145.51669"
+       y="75.111023"
        id="text3682-9"
        sodipodi:linespacing="100%"
        transform="matrix(0.99154808,-0.12973973,0.12973973,0.99154808,0,0)"><tspan
          sodipodi:role="line"
-         x="140.26605"
-         y="75.324471"
-         id="tspan3711">Ig2_Facet_Sphere_Dem3DofGeom</tspan></text>
+         x="145.51669"
+         y="75.111023"
+         id="tspan3711">Ig2_Facet_Sphere_ScGeom</tspan></text>
     <text
        xml:space="preserve"
        style="font-size:4px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:100%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
-       x="149.65134"
-       y="94.587654"
+       x="148.28229"
+       y="95.502068"
        id="text3682-9-2"
        sodipodi:linespacing="100%"
        transform="matrix(0.99283737,-0.11947368,0.11947368,0.99283737,0,0)"><tspan
          sodipodi:role="line"
-         x="149.65134"
-         y="94.587654"
+         x="148.28229"
+         y="95.502068"
          id="tspan3711-0">Ip2_FrictMat_FrictMat_FrictPhys</tspan></text>
     <flowRoot
        xml:space="preserve"
@@ -326,13 +336,6 @@
        height="24.496199"
        x="249.76022"
        y="59.129692" />
-    <rect
-       style="fill:#8800aa;fill-opacity:0.34181818;stroke:#000000;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:0.35636363;stroke-dasharray:none"
-       id="rect3832"
-       width="94.701797"
-       height="22.728432"
-       x="234.35539"
-       y="31.097958" />
     <path
        style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
        d="m 306.07622,43.289354 15.15229,0 -0.50508,33.335034 -25.75889,0"
@@ -349,6 +352,6 @@
          sodipodi:role="line"
          id="tspan3684-6"
          x="349.99075"
-         y="59.732277">Law2_Dem3DofGeom_FrictPhys_Basic</tspan></text>
+         y="59.732277">Law2_ScGeom_FrictPhys_CundallStrack</tspan></text>
   </g>
 </svg>

=== modified file 'doc/sphinx/formulation.rst'
--- doc/sphinx/formulation.rst	2012-09-08 01:19:45 +0000
+++ doc/sphinx/formulation.rst	2013-05-14 21:24:11 +0000
@@ -189,7 +189,7 @@
    
 	Series of 2 springs representing normal stiffness of contact between 2 spheres.
 				
-Let us define distance $l=l_1+l_2$, where $l_i$ are distances between contact point and sphere centers, which are initially (roughly speaking) equal to sphere radii. Change of distance between the spehre centers $\Delta l$ is distributed onto deformations of both spheres $\Delta l=\Delta l_1+\Delta l_2$ proportionally to their compliances. Displacement change $\Delta l_i$ generates force $F_i=K_i \Delta l_i$, where $K_i$ assures proportionality and has physical meaning and dimension of stiffness; $K_i$ is related to the sphere material modulus $E_i$ and some length $\tilde l_i$ proportional to $r_i$.
+Let us define distance $l=l_1+l_2$, where $l_i$ are distances between contact point and sphere centers, which are initially (roughly speaking) equal to sphere radii. Change of distance between the sphere centers $\Delta l$ is distributed onto deformations of both spheres $\Delta l=\Delta l_1+\Delta l_2$ proportionally to their compliances. Displacement change $\Delta l_i$ generates force $F_i=K_i \Delta l_i$, where $K_i$ assures proportionality and has physical meaning and dimension of stiffness; $K_i$ is related to the sphere material modulus $E_i$ and some length $\tilde l_i$ proportional to $r_i$.
 
 .. math::
 	:nowrap:
@@ -262,7 +262,7 @@
 
 Contact cross-section
 """""""""""""""""""""
-Some constitutive laws are formulated with strains and stresses (:yref:`Law2_Dem3DofGeom_CpmPhys_Cpm`, the concrete model described later, for instance); in that case, equivalent cross-section of the contact must be introduced for the sake of dimensionality. The exact definition is rather arbitrary; the CPM model (:yref:`Ip2_CpmMat_CpmMat_CpmPhys`) uses the relation
+Some constitutive laws are formulated with strains and stresses (:yref:`Law2_ScGeom_CpmPhys_Cpm`, the concrete model described later, for instance); in that case, equivalent cross-section of the contact must be introduced for the sake of dimensionality. The exact definition is rather arbitrary; the CPM model (:yref:`Ip2_CpmMat_CpmMat_CpmPhys`) uses the relation
 
 .. math:: A_{\rm eq}=\pi\min(r_1,r_2)^2
 	:label: eq-strain-crosssection
@@ -428,7 +428,7 @@
 ===========================
 Once strain on a contact is computed, it can be used to compute stresses/forces acting on both spheres.
 
-The constitutive law presented here is the most usual DEM formulation, originally proposed by Cundall. While the strain evaluation will be similar to algorithms described in the previous section regardless of stress evaluation, stress evaluation itself depends on the nature of the material being modeled. The constitutive law presented here is the most simple non-cohesive elastic case with dry friction, which Yade implements in :yref:`Law2_Dem3DofGeom_FrictPhys_Basic` (all constitutive laws derive from base class :yref:`LawFunctor`).
+The constitutive law presented here is the most usual DEM formulation, originally proposed by Cundall. While the strain evaluation will be similar to algorithms described in the previous section regardless of stress evaluation, stress evaluation itself depends on the nature of the material being modeled. The constitutive law presented here is the most simple non-cohesive elastic case with dry friction, which Yade implements in :yref:`Law2_ScGeom_FrictPhys_CundallStrack` (all constitutive laws derive from base class :yref:`LawFunctor`).
 		
 In DEM generally, some constitutive laws are expressed using strains and stresses while others prefer displacement/force formulation. The law described here falls in the latter category.
 
@@ -835,7 +835,7 @@
 ============================
 While most DEM simulations happen in $R^3$ space, it is frequently useful to avoid boundary effects by using periodic space instead. In order to satisfy periodicity conditions, periodic space is created by repetition of parallelepiped-shaped cell. In Yade, periodic space is implemented in the :yref:`Cell` class. The geometry of the cell in the reference coordinates system is defined by three edges of the parallepiped. The corresponding base vectors are stored in the columns of matrix $\mat{H}$ (:yref:`Cell.hSize`).
 
-The initial $\mat{H}$ can be explicitly defined as a 3x3 matrix at the begining of the simulation. There are no restricitions on the possible shapes: any parallelepiped is accepted as the initial cell.
+The initial $\mat{H}$ can be explicitly defined as a 3x3 matrix at the beginning of the simulation. There are no restricitions on the possible shapes: any parallelepiped is accepted as the initial cell.
 If the base vectors are axis-aligned, defining only their sizes can be more convenient than defining the full $\mat{H}$ matrix; in that case it is enough to define the norms of columns in $\mat{H}$ (see :yref:`Cell.size`).
 
 After the definition of the initial cell's geometry, $\mat{H}$ should generally not be modified by direct assignment. Instead, its deformation rate will be defined via the velocity gradient :yref:`Cell.velGrad` described below. It is the only variable that let the period deformation be correctly accounted for in constitutive laws and Newton integrator (:yref:`NewtonIntegrator`).

=== modified file 'doc/sphinx/index-toctree.rst'
--- doc/sphinx/index-toctree.rst	2011-02-11 18:26:51 +0000
+++ doc/sphinx/index-toctree.rst	2013-03-21 19:28:57 +0000
@@ -35,8 +35,6 @@
 
   modules.rst
 
-  external.rst
-
   citing.rst
 
   publications.rst

=== modified file 'doc/sphinx/installation.rst'
--- doc/sphinx/installation.rst	2012-10-22 18:56:11 +0000
+++ doc/sphinx/installation.rst	2013-03-26 19:21:11 +0000
@@ -72,12 +72,16 @@
 #. developement version (trunk) can be obtained from the `code repository <https://github.com/yade/>`_ at github.
 
 We use `GIT <http://git-scm.com/>`_ (the ``git`` command) for code 
-management (install the ``git`` package in your distribution)::
+management (install the ``git`` package in your distribution and create a GitHub account)::
 
 		git clone git@xxxxxxxxxx:yade/trunk.git
 
 will download the whole code repository of ``trunk``. Check out `Yade on github
 <https://www.yade-dem.org/wiki/Yade_on_github>`_ wiki page for more.
+
+Alternatively, a read-only checkout is possible via https without a GitHub account (easier if you don't want to modify the main Yade branch)::
+
+		git clone https://github.com/yade/trunk.git
    
 For those behind firewall, you can download `any revision  <https://www.yade-dem.org/source/>`_ of the repository as compressed archive.
 
@@ -109,7 +113,7 @@
 
 	* **Ubuntu**, **Debian** and their derivatives::
 
-		sudo apt-get install cmake git freeglut3-dev libloki-dev\
+		sudo apt-get install cmake git freeglut3-dev libloki-dev \
 		libboost-date-time-dev libboost-filesystem-dev libboost-thread-dev \
 		libboost-program-options-dev \
 		libboost-regex-dev fakeroot dpkg-dev build-essential g++ \
@@ -117,9 +121,9 @@
 		python-matplotlib libsqlite3-dev python-numpy python-tk gnuplot \
 		libgts-dev python-pygraphviz libvtk5-dev python-scientific libeigen3-dev \
 		binutils-gold python-xlib python-qt4 pyqt4-dev-tools \
-		gtk2-engines-pixbuf \
+		gtk2-engines-pixbuf python-argparse \
 		libqglviewer-qt4-dev python-imaging libjs-jquery python-sphinx python-git python-bibtex \
-		libxmu-dev libxi-dev libgmp3-dev libcgal-dev
+		libxmu-dev libxi-dev libgmp3-dev libcgal-dev help2man
 
 	* **Fedora**::
 
@@ -189,6 +193,9 @@
 and then "make doc" to build it. The generated files will be stored in your current
 build directory/doc/sphinx/_build.
 
+"make manpage" command generates and moves manpages in a standard place.
+"make check" command executes standard test to check the functionality of compiled program.
+
 Yade can be compiled not only by GCC-compiler, but also by `CLANG <http://clang.llvm.org/>`_ 
 front-end for the LLVM compiler. For that you set the environment variables CC and CXX 
 upon detecting the C and C++ compiler to use::

=== modified file 'doc/sphinx/introduction.rst'
--- doc/sphinx/introduction.rst	2012-07-17 19:31:16 +0000
+++ doc/sphinx/introduction.rst	2013-04-24 19:49:00 +0000
@@ -80,12 +80,10 @@
 	  -x                    Exit when the script finishes
 	  -n                    Run without graphical interface (equivalent to
 	                        unsetting the DISPLAY environment variable)
-	  --generate-manpage=FILE
-	                        Generate man page documenting this program and exit
 	  --test                Run regression test suite and exit; the exists status
 	                        is 0 if all tests pass, 1 if a test fails and 2 for an
 	                        unspecified exception.
-	  --checks              Run a series of user-defined check tests as described
+	  --check               Run a series of user-defined check tests as described
 	                        in /build/buildd/yade-
 	                        daily-1+3021+27~lucid1/scripts/test/checks/README
 	  --performance         Starts a test to measure the productivity
@@ -354,7 +352,7 @@
 .. ipython::
 	:suppress:
 
-	In [1]: O.engines=[InteractionLoop([Ig2_Sphere_Sphere_Dem3DofGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[])]
+	In [1]: O.engines=[InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[])]
 
 	In [2]: utils.createInteraction(0,1);
 
@@ -372,7 +370,7 @@
 	(0, 1)
 
 	In [4]: i.geom
-	<Dem3Dof_Sphere_Sphere instance at 0x9403838>
+	<ScGeom instance at 0x9403838>
 
 	In [5]: i.phys
 	<ElasticContactInteraction instance at 0x94038d0>
@@ -439,9 +437,9 @@
 		InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]),
 		# handle interactions
 		InteractionLoop(
-			[Ig2_Sphere_Sphere_Dem3DofGeom(),Ig2_Facet_Sphere_Dem3DofGeom()],
+			[Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom()],
 			[Ip2_FrictMat_FrictMat_FrictPhys()],
-			[Law2_Dem3Dof_Elastic_Elastic()],
+			[Law2_ScGeom_FrictPhys_CundallStrack()],
 		),
 		# apply other conditions
 		GravityEngine(gravity=(0,0,-9.81)),
@@ -478,9 +476,9 @@
 .. code-block:: python
 
 	InteractionLoop(
-		[Ig2_Sphere_Sphere_Dem3DofGeom(),Ig2_Facet_Sphere_Dem3DofGeom()],
+		[Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom()],
 		[Ip2_FrictMat_FrictMat_FrictPhys()],
-		[Law2_Dem3Dof_Elastic_Elastic()],
+		[Law2_ScGeom_FrictPhys_CundallStrack()],
 	),
 
 hides 3 internal dispatchers within the :yref:`InteractionLoop` engine; they all operate on interactions and are, for performance reasons, put together:
@@ -488,9 +486,9 @@
 :yref:`IGeomDispatcher`
 	uses the first set of functors (``Ig2``), which are dispatched based on combination of ``2`` :yref:`Shapes<Shapes>` objects. Dispatched functor resolves exact collision configuration and creates :yref:`IGeom<Interaction::geom>` (whence ``Ig`` in the name) associated with the interaction, if there is collision. The functor might as well fail on approximate interactions, indicating there is no real contact between the bodies, even if they did overlap in the approximate collision detection.
 
-	#. The first functor, :yref:`Ig2_Sphere_Sphere_Dem3DofGeom`, is called on interaction of 2 :yref:`Spheres<Sphere>` and creates :yref:`Dem3DofGeom` instance, if appropriate.
+	#. The first functor, :yref:`Ig2_Sphere_Sphere_ScGeom`, is called on interaction of 2 :yref:`Spheres<Sphere>` and creates :yref:`ScGeom` instance, if appropriate.
 
-	#. The second functor, :yref:`Ig2_Facet_Sphere_Dem3DofGeom`, is called for interaction of :yref:`Facet` with :yref:`Sphere` and might create (again) a :yref:`Dem3DofGeom` instance.
+	#. The second functor, :yref:`Ig2_Facet_Sphere_ScGeom`, is called for interaction of :yref:`Facet` with :yref:`Sphere` and might create (again) a :yref:`ScGeom` instance.
 
 	All ``Ig2`` functors derive from :yref:`IGeomFunctor` (they are documented at the same place).
 
@@ -510,5 +508,7 @@
 .. figure:: fig/dispatch-loop.*
 	:width: 13cm
 
-	Chain of functors producing and accepting certain types. In the case shown, the ``Ig2`` functors produce :yref:`Dem3DofGeom` instances from all handled :yref:`Shape` combinations; the ``Ig2`` functor produces :yref:`FrictMat`. The constitutive law functor ``Law2`` accepts the combination of types produced. Note that the types are stated in the functor's class names.
+	Chain of functors producing and accepting certain types. In the case shown, the ``Ig2`` functors produce :yref:`ScfGeom` instances from all handled :yref:`Shape` combinations; the ``Ig2`` functor produces :yref:`FrictMat`. The constitutive law functor ``Law2`` accepts the combination of types produced. Note that the types are stated in the functor's class names.
 
+.. note::
+	When Yade starts, O.engines is filled with a reasonable default list, so that it is not strictly necessary to redefine it when trying simple things. The default scene will handle spheres, boxes, and facets with :yref:`frictional<FrictMat>` properties correctly, and adjusts the timestep dynamically. You can find an example in simple-scene-default-engines.py.

=== added file 'doc/sphinx/ipython_directive013.py'
--- doc/sphinx/ipython_directive013.py	1970-01-01 00:00:00 +0000
+++ doc/sphinx/ipython_directive013.py	2013-03-01 21:44:07 +0000
@@ -0,0 +1,831 @@
+# -*- coding: utf-8 -*-
+"""Sphinx directive to support embedded IPython code.
+From: https://github.com/ipython/ipython/blob/master/docs/sphinxext/ipython_directive.py
+
+This directive allows pasting of entire interactive IPython sessions, prompts
+and all, and their code will actually get re-executed at doc build time, with
+all prompts renumbered sequentially. It also allows you to input code as a pure
+python input by giving the argument python to the directive. The output looks
+like an interactive ipython section.
+
+To enable this directive, simply list it in your Sphinx ``conf.py`` file
+(making sure the directory where you placed it is visible to sphinx, as is
+needed for all Sphinx directives).
+
+By default this directive assumes that your prompts are unchanged IPython ones,
+but this can be customized. The configurable options that can be placed in
+conf.py are
+
+ipython_savefig_dir:
+    The directory in which to save the figures. This is relative to the
+    Sphinx source directory. The default is `html_static_path`.
+ipython_rgxin:
+    The compiled regular expression to denote the start of IPython input
+    lines. The default is re.compile('In \[(\d+)\]:\s?(.*)\s*'). You
+    shouldn't need to change this.
+ipython_rgxout:
+    The compiled regular expression to denote the start of IPython output
+    lines. The default is re.compile('Out\[(\d+)\]:\s?(.*)\s*'). You
+    shouldn't need to change this.
+ipython_promptin:
+    The string to represent the IPython input prompt in the generated ReST.
+    The default is 'In [%d]:'. This expects that the line numbers are used
+    in the prompt.
+ipython_promptout:
+
+    The string to represent the IPython prompt in the generated ReST. The
+    default is 'Out [%d]:'. This expects that the line numbers are used
+    in the prompt.
+
+ToDo
+----
+
+- Turn the ad-hoc test() function into a real test suite.
+- Break up ipython-specific functionality from matplotlib stuff into better
+  separated code.
+
+Authors
+-------
+
+- John D Hunter: orignal author.
+- Fernando Perez: refactoring, documentation, cleanups, port to 0.11.
+- VáclavŠmilauer <eudoxos-AT-arcig.cz>: Prompt generalizations.
+- Skipper Seabold, refactoring, cleanups, pure python addition
+"""
+
+#-----------------------------------------------------------------------------
+# Imports
+#-----------------------------------------------------------------------------
+
+# Stdlib
+import cStringIO
+import os
+import re
+import sys
+import tempfile
+import ast
+
+# To keep compatibility with various python versions
+try:
+    from hashlib import md5
+except ImportError:
+    from md5 import md5
+
+# Third-party
+import matplotlib
+import sphinx
+from docutils.parsers.rst import directives
+from docutils import nodes
+from sphinx.util.compat import Directive
+
+matplotlib.use('Agg')
+
+# Our own
+from IPython import Config, InteractiveShell
+from IPython.core.profiledir import ProfileDir
+from IPython.utils import io
+
+#-----------------------------------------------------------------------------
+# Globals
+#-----------------------------------------------------------------------------
+# for tokenizing blocks
+COMMENT, INPUT, OUTPUT =  range(3)
+
+#-----------------------------------------------------------------------------
+# Functions and class declarations
+#-----------------------------------------------------------------------------
+def block_parser(part, rgxin, rgxout, fmtin, fmtout):
+    """
+    part is a string of ipython text, comprised of at most one
+    input, one ouput, comments, and blank lines.  The block parser
+    parses the text into a list of::
+
+      blocks = [ (TOKEN0, data0), (TOKEN1, data1), ...]
+
+    where TOKEN is one of [COMMENT | INPUT | OUTPUT ] and
+    data is, depending on the type of token::
+
+      COMMENT : the comment string
+
+      INPUT: the (DECORATOR, INPUT_LINE, REST) where
+         DECORATOR: the input decorator (or None)
+         INPUT_LINE: the input as string (possibly multi-line)
+         REST : any stdout generated by the input line (not OUTPUT)
+
+
+      OUTPUT: the output string, possibly multi-line
+    """
+
+    block = []
+    lines = part.split('\n')
+    N = len(lines)
+    i = 0
+    decorator = None
+    while 1:
+
+        if i==N:
+            # nothing left to parse -- the last line
+            break
+
+        line = lines[i]
+        i += 1
+        line_stripped = line.strip()
+        if line_stripped.startswith('#'):
+            block.append((COMMENT, line))
+            continue
+
+        if line_stripped.startswith('@'):
+            # we're assuming at most one decorator -- may need to
+            # rethink
+            decorator = line_stripped
+            continue
+
+        # does this look like an input line?
+        matchin = rgxin.match(line)
+        if matchin:
+            lineno, inputline = int(matchin.group(1)), matchin.group(2)
+
+            # the ....: continuation string
+            continuation = '   %s:'%''.join(['.']*(len(str(lineno))+2))
+            Nc = len(continuation)
+            # input lines can continue on for more than one line, if
+            # we have a '\' line continuation char or a function call
+            # echo line 'print'.  The input line can only be
+            # terminated by the end of the block or an output line, so
+            # we parse out the rest of the input line if it is
+            # multiline as well as any echo text
+
+            rest = []
+            while i<N:
+
+                # look ahead; if the next line is blank, or a comment, or
+                # an output line, we're done
+
+                nextline = lines[i]
+                matchout = rgxout.match(nextline)
+                #print "nextline=%s, continuation=%s, starts=%s"%(nextline, continuation, nextline.startswith(continuation))
+                if matchout or nextline.startswith('#'):
+                    break
+                elif nextline.startswith(continuation):
+                    inputline += '\n' + nextline[Nc:]
+                else:
+                    rest.append(nextline)
+                i+= 1
+
+            block.append((INPUT, (decorator, inputline, '\n'.join(rest))))
+            continue
+
+        # if it looks like an output line grab all the text to the end
+        # of the block
+        matchout = rgxout.match(line)
+        if matchout:
+            lineno, output = int(matchout.group(1)), matchout.group(2)
+            if i<N-1:
+                output = '\n'.join([output] + lines[i:])
+
+            block.append((OUTPUT, output))
+            break
+
+    return block
+
+class EmbeddedSphinxShell(object):
+    """An embedded IPython instance to run inside Sphinx"""
+
+    def __init__(self):
+
+        self.cout = cStringIO.StringIO()
+
+
+        # Create config object for IPython
+        config = Config()
+        config.Global.display_banner = False
+        config.Global.exec_lines = ['import numpy as np',
+                                    'from pylab import *'
+                                    ]
+        config.InteractiveShell.autocall = False
+        config.InteractiveShell.autoindent = False
+        config.InteractiveShell.colors = 'NoColor'
+
+        # create a profile so instance history isn't saved
+        tmp_profile_dir = tempfile.mkdtemp(prefix='profile_')
+        profname = 'auto_profile_sphinx_build'
+        pdir = os.path.join(tmp_profile_dir,profname)
+        profile = ProfileDir.create_profile_dir(pdir)
+
+        # Create and initialize ipython, but don't start its mainloop
+        IP = InteractiveShell.instance(config=config, profile_dir=profile)
+        # io.stdout redirect must be done *after* instantiating InteractiveShell
+        io.stdout = self.cout
+        io.stderr = self.cout
+
+        # For debugging, so we can see normal output, use this:
+        #from IPython.utils.io import Tee
+        #io.stdout = Tee(self.cout, channel='stdout') # dbg
+        #io.stderr = Tee(self.cout, channel='stderr') # dbg
+
+        # Store a few parts of IPython we'll need.
+        self.IP = IP
+        self.user_ns = self.IP.user_ns
+        self.user_global_ns = self.IP.user_global_ns
+
+        self.input = ''
+        self.output = ''
+
+        self.is_verbatim = False
+        self.is_doctest = False
+        self.is_suppress = False
+
+        # on the first call to the savefig decorator, we'll import
+        # pyplot as plt so we can make a call to the plt.gcf().savefig
+        self._pyplot_imported = False
+
+    def clear_cout(self):
+        self.cout.seek(0)
+        self.cout.truncate(0)
+
+    def process_input_line(self, line, store_history=True):
+        """process the input, capturing stdout"""
+        #print "input='%s'"%self.input
+        stdout = sys.stdout
+        splitter = self.IP.input_splitter
+        try:
+            sys.stdout = self.cout
+            splitter.push(line)
+            more = splitter.push_accepts_more()
+            if not more:
+                source_raw = splitter.source_raw_reset()[1]
+                self.IP.run_cell(source_raw, store_history=store_history)
+        finally:
+            sys.stdout = stdout
+
+    def process_image(self, decorator):
+        """
+        # build out an image directive like
+        # .. image:: somefile.png
+        #    :width 4in
+        #
+        # from an input like
+        # savefig somefile.png width=4in
+        """
+        savefig_dir = self.savefig_dir
+        source_dir = self.source_dir
+        saveargs = decorator.split(' ')
+        filename = saveargs[1]
+        # insert relative path to image file in source
+        outfile = os.path.relpath(os.path.join(savefig_dir,filename),
+                    source_dir)
+
+        imagerows = ['.. image:: %s'%outfile]
+
+        for kwarg in saveargs[2:]:
+            arg, val = kwarg.split('=')
+            arg = arg.strip()
+            val = val.strip()
+            imagerows.append('   :%s: %s'%(arg, val))
+
+        image_file = os.path.basename(outfile) # only return file name
+        image_directive = '\n'.join(imagerows)
+        return image_file, image_directive
+
+
+    # Callbacks for each type of token
+    def process_input(self, data, input_prompt, lineno):
+        """Process data block for INPUT token."""
+        decorator, input, rest = data
+        image_file = None
+        image_directive = None
+        #print 'INPUT:', data  # dbg
+        is_verbatim = decorator=='@verbatim' or self.is_verbatim
+        is_doctest = decorator=='@doctest' or self.is_doctest
+        is_suppress = decorator=='@suppress' or self.is_suppress
+        is_savefig = decorator is not None and \
+                     decorator.startswith('@savefig')
+
+        input_lines = input.split('\n')
+        if len(input_lines) > 1:
+            if input_lines[-1] != "":
+                input_lines.append('') # make sure there's a blank line
+                                       # so splitter buffer gets reset
+
+        continuation = '   %s:'%''.join(['.']*(len(str(lineno))+2))
+        Nc = len(continuation)
+
+        if is_savefig:
+            image_file, image_directive = self.process_image(decorator)
+
+        ret = []
+        is_semicolon = False
+
+        for i, line in enumerate(input_lines):
+            if line.endswith(';'):
+                is_semicolon = True
+
+            if i==0:
+                # process the first input line
+                if is_verbatim:
+                    self.process_input_line('')
+                    self.IP.execution_count += 1 # increment it anyway
+                else:
+                    # only submit the line in non-verbatim mode
+                    self.process_input_line(line, store_history=True)
+                formatted_line = '%s %s'%(input_prompt, line)
+            else:
+                # process a continuation line
+                if not is_verbatim:
+                    self.process_input_line(line, store_history=True)
+
+                formatted_line = '%s %s'%(continuation, line)
+
+            if not is_suppress:
+                ret.append(formatted_line)
+
+        if not is_suppress and len(rest.strip()) and is_verbatim:
+            # the "rest" is the standard output of the
+            # input, which needs to be added in
+            # verbatim mode
+            ret.append(rest)
+
+        self.cout.seek(0)
+        output = self.cout.read()
+        if not is_suppress and not is_semicolon:
+            ret.append(output)
+        elif is_semicolon: # get spacing right
+            ret.append('')
+
+        self.cout.truncate(0)
+        return (ret, input_lines, output, is_doctest, image_file,
+                    image_directive)
+        #print 'OUTPUT', output  # dbg
+
+    def process_output(self, data, output_prompt,
+                       input_lines, output, is_doctest, image_file):
+        """Process data block for OUTPUT token."""
+        if is_doctest:
+            submitted = data.strip()
+            found = output
+            if found is not None:
+                found = found.strip()
+
+                # XXX - fperez: in 0.11, 'output' never comes with the prompt
+                # in it, just the actual output text.  So I think all this code
+                # can be nuked...
+
+                # the above comment does not appear to be accurate... (minrk)
+
+                ind = found.find(output_prompt)
+                if ind<0:
+                    e='output prompt="%s" does not match out line=%s' % \
+                       (output_prompt, found)
+                    raise RuntimeError(e)
+                found = found[len(output_prompt):].strip()
+
+                if found!=submitted:
+                    e = ('doctest failure for input_lines="%s" with '
+                         'found_output="%s" and submitted output="%s"' %
+                         (input_lines, found, submitted) )
+                    raise RuntimeError(e)
+                #print 'doctest PASSED for input_lines="%s" with found_output="%s" and submitted output="%s"'%(input_lines, found, submitted)
+
+    def process_comment(self, data):
+        """Process data fPblock for COMMENT token."""
+        if not self.is_suppress:
+            return [data]
+
+    def save_image(self, image_file):
+        """
+        Saves the image file to disk.
+        """
+        self.ensure_pyplot()
+        command = 'plt.gcf().savefig("%s")'%image_file
+        #print 'SAVEFIG', command  # dbg
+        self.process_input_line('bookmark ipy_thisdir', store_history=False)
+        self.process_input_line('cd -b ipy_savedir', store_history=False)
+        self.process_input_line(command, store_history=False)
+        self.process_input_line('cd -b ipy_thisdir', store_history=False)
+        self.process_input_line('bookmark -d ipy_thisdir', store_history=False)
+        self.clear_cout()
+
+
+    def process_block(self, block):
+        """
+        process block from the block_parser and return a list of processed lines
+        """
+        ret = []
+        output = None
+        input_lines = None
+        lineno = self.IP.execution_count
+
+        input_prompt = self.promptin%lineno
+        output_prompt = self.promptout%lineno
+        image_file = None
+        image_directive = None
+
+        for token, data in block:
+            if token==COMMENT:
+                out_data = self.process_comment(data)
+            elif token==INPUT:
+                (out_data, input_lines, output, is_doctest, image_file,
+                    image_directive) = \
+                          self.process_input(data, input_prompt, lineno)
+            elif token==OUTPUT:
+                out_data = \
+                    self.process_output(data, output_prompt,
+                                        input_lines, output, is_doctest,
+                                        image_file)
+            if out_data:
+                ret.extend(out_data)
+
+        # save the image files
+        if image_file is not None:
+            self.save_image(image_file)
+
+        return ret, image_directive
+
+    def ensure_pyplot(self):
+        if self._pyplot_imported:
+            return
+        self.process_input_line('import matplotlib.pyplot as plt',
+                                store_history=False)
+
+    def process_pure_python(self, content):
+        """
+        content is a list of strings. it is unedited directive conent
+
+        This runs it line by line in the InteractiveShell, prepends
+        prompts as needed capturing stderr and stdout, then returns
+        the content as a list as if it were ipython code
+        """
+        output = []
+        savefig = False # keep up with this to clear figure
+        multiline = False # to handle line continuation
+        multiline_start = None
+        fmtin = self.promptin
+
+        ct = 0
+
+        for lineno, line in enumerate(content):
+
+            line_stripped = line.strip()
+            if not len(line):
+                output.append(line)
+                continue
+
+            # handle decorators
+            if line_stripped.startswith('@'):
+                output.extend([line])
+                if 'savefig' in line:
+                    savefig = True # and need to clear figure
+                continue
+
+            # handle comments
+            if line_stripped.startswith('#'):
+                output.extend([line])
+                continue
+
+            # deal with lines checking for multiline
+            continuation  = u'   %s:'% ''.join(['.']*(len(str(ct))+2))
+            if not multiline:
+                modified = u"%s %s" % (fmtin % ct, line_stripped)
+                output.append(modified)
+                ct += 1
+                try:
+                    ast.parse(line_stripped)
+                    output.append(u'')
+                except Exception: # on a multiline
+                    multiline = True
+                    multiline_start = lineno
+            else: # still on a multiline
+                modified = u'%s %s' % (continuation, line)
+                output.append(modified)
+                try:
+                    mod = ast.parse(
+                            '\n'.join(content[multiline_start:lineno+1]))
+                    if isinstance(mod.body[0], ast.FunctionDef):
+                        # check to see if we have the whole function
+                        for element in mod.body[0].body:
+                            if isinstance(element, ast.Return):
+                                multiline = False
+                    else:
+                        output.append(u'')
+                        multiline = False
+                except Exception:
+                    pass
+
+            if savefig: # clear figure if plotted
+                self.ensure_pyplot()
+                self.process_input_line('plt.clf()', store_history=False)
+                self.clear_cout()
+                savefig = False
+
+        return output
+
+class IpythonDirective(Directive):
+
+    has_content = True
+    required_arguments = 0
+    optional_arguments = 4 # python, suppress, verbatim, doctest
+    final_argumuent_whitespace = True
+    option_spec = { 'python': directives.unchanged,
+                    'suppress' : directives.flag,
+                    'verbatim' : directives.flag,
+                    'doctest' : directives.flag,
+                  }
+
+    shell = EmbeddedSphinxShell()
+
+    def get_config_options(self):
+        # contains sphinx configuration variables
+        config = self.state.document.settings.env.config
+
+        # get config variables to set figure output directory
+        confdir = self.state.document.settings.env.app.confdir
+        savefig_dir = config.ipython_savefig_dir
+        source_dir = os.path.dirname(self.state.document.current_source)
+        if savefig_dir is None:
+            savefig_dir = config.html_static_path
+        if isinstance(savefig_dir, list):
+            savefig_dir = savefig_dir[0] # safe to assume only one path?
+        savefig_dir = os.path.join(confdir, savefig_dir)
+
+        # get regex and prompt stuff
+        rgxin     = config.ipython_rgxin
+        rgxout    = config.ipython_rgxout
+        promptin  = config.ipython_promptin
+        promptout = config.ipython_promptout
+
+        return savefig_dir, source_dir, rgxin, rgxout, promptin, promptout
+
+    def setup(self):
+        # reset the execution count if we haven't processed this doc
+        #NOTE: this may be borked if there are multiple seen_doc tmp files
+        #check time stamp?
+        seen_docs = [i for i in os.listdir(tempfile.tempdir)
+            if i.startswith('seen_doc')]
+        if seen_docs:
+            fname = os.path.join(tempfile.tempdir, seen_docs[0])
+            docs = open(fname).read().split('\n')
+            if not self.state.document.current_source in docs:
+                self.shell.IP.history_manager.reset()
+                self.shell.IP.execution_count = 1
+        else: # haven't processed any docs yet
+            docs = []
+
+
+        # get config values
+        (savefig_dir, source_dir, rgxin,
+                rgxout, promptin, promptout) = self.get_config_options()
+
+        # and attach to shell so we don't have to pass them around
+        self.shell.rgxin = rgxin
+        self.shell.rgxout = rgxout
+        self.shell.promptin = promptin
+        self.shell.promptout = promptout
+        self.shell.savefig_dir = savefig_dir
+        self.shell.source_dir = source_dir
+
+        # setup bookmark for saving figures directory
+
+        self.shell.process_input_line('bookmark ipy_savedir %s'%savefig_dir,
+                                      store_history=False)
+        self.shell.clear_cout()
+
+        # write the filename to a tempfile because it's been "seen" now
+        if not self.state.document.current_source in docs:
+            fd, fname = tempfile.mkstemp(prefix="seen_doc", text=True)
+            fout = open(fname, 'a')
+            fout.write(self.state.document.current_source+'\n')
+            fout.close()
+
+        return rgxin, rgxout, promptin, promptout
+
+
+    def teardown(self):
+        # delete last bookmark
+        self.shell.process_input_line('bookmark -d ipy_savedir',
+                                      store_history=False)
+        self.shell.clear_cout()
+
+    def run(self):
+        debug = False
+
+        #TODO, any reason block_parser can't be a method of embeddable shell
+        # then we wouldn't have to carry these around
+        rgxin, rgxout, promptin, promptout = self.setup()
+
+        options = self.options
+        self.shell.is_suppress = 'suppress' in options
+        self.shell.is_doctest = 'doctest' in options
+        self.shell.is_verbatim = 'verbatim' in options
+
+
+        # handle pure python code
+        if 'python' in self.arguments:
+            content = self.content
+            self.content = self.shell.process_pure_python(content)
+
+        parts = '\n'.join(self.content).split('\n\n')
+
+        lines = ['.. code-block:: ipython','']
+        figures = []
+
+        for part in parts:
+
+            block = block_parser(part, rgxin, rgxout, promptin, promptout)
+
+            if len(block):
+                rows, figure = self.shell.process_block(block)
+                for row in rows:
+                    lines.extend(['   %s'%line for line in row.split('\n')])
+
+                if figure is not None:
+                    figures.append(figure)
+
+        #text = '\n'.join(lines)
+        #figs = '\n'.join(figures)
+
+        for figure in figures:
+            lines.append('')
+            lines.extend(figure.split('\n'))
+            lines.append('')
+
+        #print lines
+        if len(lines)>2:
+            if debug:
+                print '\n'.join(lines)
+            else: #NOTE: this raises some errors, what's it for?
+                #print 'INSERTING %d lines'%len(lines)
+                self.state_machine.insert_input(
+                    lines, self.state_machine.input_lines.source(0))
+
+        text = '\n'.join(lines)
+        txtnode = nodes.literal_block(text, text)
+        txtnode['language'] = 'ipython'
+        #imgnode = nodes.image(figs)
+
+        # cleanup
+        self.teardown()
+
+        return []#, imgnode]
+
+# Enable as a proper Sphinx directive
+def setup(app):
+    setup.app = app
+
+    app.add_directive('ipython', IpythonDirective)
+    app.add_config_value('ipython_savefig_dir', None, True)
+    app.add_config_value('ipython_rgxin',
+                         re.compile('In \[(\d+)\]:\s?(.*)\s*'), True)
+    app.add_config_value('ipython_rgxout',
+                         re.compile('Out\[(\d+)\]:\s?(.*)\s*'), True)
+    app.add_config_value('ipython_promptin', 'In [%d]:', True)
+    app.add_config_value('ipython_promptout', 'Out[%d]:', True)
+
+
+# Simple smoke test, needs to be converted to a proper automatic test.
+def test():
+
+    examples = [
+        r"""
+In [9]: pwd
+Out[9]: '/home/jdhunter/py4science/book'
+
+In [10]: cd bookdata/
+/home/jdhunter/py4science/book/bookdata
+
+In [2]: from pylab import *
+
+In [2]: ion()
+
+In [3]: im = imread('stinkbug.png')
+
+@savefig mystinkbug.png width=4in
+In [4]: imshow(im)
+Out[4]: <matplotlib.image.AxesImage object at 0x39ea850>
+
+""",
+        r"""
+
+In [1]: x = 'hello world'
+
+# string methods can be
+# used to alter the string
+@doctest
+In [2]: x.upper()
+Out[2]: 'HELLO WORLD'
+
+@verbatim
+In [3]: x.st<TAB>
+x.startswith  x.strip
+""",
+    r"""
+
+In [130]: url = 'http://ichart.finance.yahoo.com/table.csv?s=CROX\
+   .....: &d=9&e=22&f=2009&g=d&a=1&br=8&c=2006&ignore=.csv'
+
+In [131]: print url.split('&')
+['http://ichart.finance.yahoo.com/table.csv?s=CROX', 'd=9', 'e=22', 'f=2009', 'g=d', 'a=1', 'b=8', 'c=2006', 'ignore=.csv']
+
+In [60]: import urllib
+
+""",
+    r"""\
+
+In [133]: import numpy.random
+
+@suppress
+In [134]: numpy.random.seed(2358)
+
+@doctest
+In [135]: numpy.random.rand(10,2)
+Out[135]:
+array([[ 0.64524308,  0.59943846],
+       [ 0.47102322,  0.8715456 ],
+       [ 0.29370834,  0.74776844],
+       [ 0.99539577,  0.1313423 ],
+       [ 0.16250302,  0.21103583],
+       [ 0.81626524,  0.1312433 ],
+       [ 0.67338089,  0.72302393],
+       [ 0.7566368 ,  0.07033696],
+       [ 0.22591016,  0.77731835],
+       [ 0.0072729 ,  0.34273127]])
+
+""",
+
+    r"""
+In [106]: print x
+jdh
+
+In [109]: for i in range(10):
+   .....:     print i
+   .....:
+   .....:
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+""",
+
+        r"""
+
+In [144]: from pylab import *
+
+In [145]: ion()
+
+# use a semicolon to suppress the output
+@savefig test_hist.png width=4in
+In [151]: hist(np.random.randn(10000), 100);
+
+
+@savefig test_plot.png width=4in
+In [151]: plot(np.random.randn(10000), 'o');
+   """,
+
+        r"""
+# use a semicolon to suppress the output
+In [151]: plt.clf()
+
+@savefig plot_simple.png width=4in
+In [151]: plot([1,2,3])
+
+@savefig hist_simple.png width=4in
+In [151]: hist(np.random.randn(10000), 100);
+
+""",
+     r"""
+# update the current fig
+In [151]: ylabel('number')
+
+In [152]: title('normal distribution')
+
+
+@savefig hist_with_text.png
+In [153]: grid(True)
+
+        """,
+        ]
+    # skip local-file depending first example:
+    examples = examples[1:]
+
+    #ipython_directive.DEBUG = True  # dbg
+    #options = dict(suppress=True)  # dbg
+    options = dict()
+    for example in examples:
+        content = example.split('\n')
+        ipython_directive('debug', arguments=None, options=options,
+                          content=content, lineno=0,
+                          content_offset=None, block_text=None,
+                          state=None, state_machine=None,
+                          )
+
+# Run test suite as a script
+if __name__=='__main__':
+    if not os.path.isdir('_static'):
+        os.mkdir('_static')
+    test()
+    print 'All OK? Check figures in _static/'

=== modified file 'doc/sphinx/prog.rst'
--- doc/sphinx/prog.rst	2012-09-08 01:19:45 +0000
+++ doc/sphinx/prog.rst	2013-04-24 19:49:00 +0000
@@ -175,7 +175,6 @@
 * programming style
 
   * Be defensive, if it has no significant performance impact. Use assertions abundantly: they don't affect performance (in the optimized build) and make spotting error conditions much easier.
-  * Use logging abundantly. Again, ``LOG_TRACE`` and ``LOG_DEBUG`` are eliminated from optimized code; unless turned on explicitly, the ouput will be suppressed even in the debug build (see below).
   * Use ``YADE_CAST`` and ``YADE_PTR_CAST`` where you want type-check during debug builds, but fast casting in optimized build. 
   * Initialize all class variables in the default constructor. This avoids bugs that may manifest randomly and are difficult to fix. Initializing with NaN's will help you find otherwise unitialized variable. (This is taken care of by :ref:`YADE_CLASS_BASE_DOC` macros for user classes)
 
@@ -215,8 +214,8 @@
 	To give a few examples:
 
 	* :yref:`Bo1_Sphere_Aabb` is a :yref:`BoundFunctor` which is called for :yref:`Sphere`, creating an instance of :yref:`Aabb`.
-	* :yref:`Ig2_Facet_Sphere_Dem3DofGeom` is binary functor called for :yref:`Facet` and :yref:`Sphere`, creating and instace of :yref:`Dem3DofGeom`.
-	* :yref:`Law2_Dem3DofGeom_CpmPhys_Cpm` is binary functor (:yref:`LawFunctor`) called for types :yref:`Dem3Dof (Geom)<Dem3DofGeom>` and :yref:`CpmPhys`.
+	* :yref:`Ig2_Facet_Sphere_ScGeom` is binary functor called for :yref:`Facet` and :yref:`Sphere`, creating and instace of :yref:`ScGeom`.
+	* :yref:`Law2_ScGeom_CpmPhys_Cpm` is binary functor (:yref:`LawFunctor`) called for types :yref:`ScGeom (Geom)<ScGeom>` and :yref:`CpmPhys`.
 
 .. [#opengldispatchers] Not considering OpenGL dispatchers, which might be replaced by regular virtual functions in the future.
 
@@ -389,7 +388,7 @@
 
 Eigen provides full rich linear algebra functionality. Some code firther uses the [cgal]_ library for computational geometry.
 
-In Python, basic numeric types are wrapped and imported from the ``miniEigen`` module; the types drop the ``r`` type qualifier at the end, the syntax is otherwise similar. ``Se3r`` is not wrapped at all, only converted automatically, rarely as it is needed, from/to a ``(Vector3,Quaternion)`` tuple/list.
+In Python, basic numeric types are wrapped and imported from the ``minieigen`` module; the types drop the ``r`` type qualifier at the end, the syntax is otherwise similar. ``Se3r`` is not wrapped at all, only converted automatically, rarely as it is needed, from/to a ``(Vector3,Quaternion)`` tuple/list.
 
 .. ipython::
 
@@ -989,11 +988,11 @@
 
 .. ipython::
 
-	Yade [7]: Dem3DofGeom().dispHierarchy()       # parent class of all other Dem3DofGeom_ classes
-
-	Yade [8]: Dem3DofGeom_SphereSphere().dispHierarchy(), Dem3DofGeom_FacetSphere().dispHierarchy(), Dem3DofGeom_WallSphere().dispHierarchy()
-
-	Yade [8]: Dem3DofGeom_WallSphere().dispHierarchy(names=False)   # show numeric indices instead
+	Yade [7]: ScGeom().dispHierarchy()       # parent class of all other ScGeom_ classes
+
+	Yade [8]: ScGridCoGeom().dispHierarchy(), ScGeom6D().dispHierarchy(), CylScGeom().dispHierarchy()
+
+	Yade [8]: CylScGeom().dispHierarchy(names=False)   # show numeric indices instead
 
 
 Dispatchers can also be inspected, using the .dispMatrix() method:
@@ -1001,9 +1000,9 @@
 .. ipython::
 
 	Yade [3]: ig=IGeomDispatcher([
-	   ...:    Ig2_Sphere_Sphere_Dem3DofGeom(),
-	   ...:    Ig2_Facet_Sphere_Dem3DofGeom(),
-	   ...:    Ig2_Wall_Sphere_Dem3DofGeom()
+	   ...:    Ig2_Sphere_Sphere_ScGeom(),
+	   ...:    Ig2_Facet_Sphere_ScGeom(),
+	   ...:    Ig2_Wall_Sphere_ScGeom()
 	   ...: ])
 
 	Yade [4]: ig.dispMatrix()
@@ -1016,13 +1015,13 @@
 
 .. ipython::
 
-	Yade [6]: ld=LawDispatcher([Law2_Dem3DofGeom_CpmPhys_Cpm()])
+	Yade [6]: ld=LawDispatcher([Law2_ScGeom_CpmPhys_Cpm()])
 
 	Yade [7]: ld.dispMatrix()
 
-	# see how the entry for Dem3DofGeom_SphereSphere will be filled after this request
+	# see how the entry for ScGridCoGeom will be filled after this request
 
-	Yade [8]: ld.dispFunctor(Dem3DofGeom_SphereSphere(),CpmPhys())       
+	Yade [8]: ld.dispFunctor(ScGridCoGeom(),CpmPhys())       
 
 	Yade [9]: ld.dispMatrix()
 
@@ -1102,63 +1101,6 @@
 * simultaneously writeable container for :ref:`ForceContainer`,
 * mutex for :yref:`Body::state`.
 
-.. _logging:
-
-Logging
---------
-
-Regardless of whether the library log4cxx is used or not, yade provides logging macros. [#log4cxxup]_ If log4cxx is enabled, these macros internally operate on the local logger instance (named ``logger``, but that is hidden for the user); if log4cxx is disabled, they send their arguments to standard error output (``cerr``).
-
-.. [#log4cxxup] Because of (seemingly?) no upstream development of log4cxx and a few problems it has, Yade will very likely move to the hypothetical ``boost::logging`` library once it exists. The logging code will not have to be changed, however, as the log4cxx logic is hidden behind these macros.
-
-Log messages are classified by their *severity*, which is one of ``TRACE`` (tracing variables), ``DEBUG`` (generally uninsteresting messages useful for debugging), ``INFO`` (information messages -- only use sparingly), ``WARN`` (warning), ``FATAL`` (serious error, consider throwing an exception with description instead). Logging level determines which messages will be shown -- by default, ``INFO`` and higher will be shown; if you run yade with ``-v`` or ``-vv``, ``DEBUG`` and ``TRACE`` messages will be also enabled (with log4cxx).
-
-Every class using logging should create logger using these 2 macros (they expand to nothing if log4cxx is not used):
-
-``DECLARE_LOGGER;``
-	in class declaration body (in the ``.hpp`` file); this declares static variable ``logger``;
-``CREATE_LOGGER(ClassName);``
-	in the implementation file; it creates and initializes that static variable. The logger will be named ``yade.ClassName``.
-
-The logging macros are the following:
-
-* ``LOG_TRACE``, ``LOG_DEBUG``, ``LOG_INFO``, ``LOG_WARN``, ``LOG_ERROR``, ``LOG_FATAL`` (increasing severity); their argument is fed to the logger stream, hence can contain the ``<<`` operation:
-
-	.. code-block:: c++
-
-		LOG_WARN("Exceeded "<<maxSteps<<" steps in attempts to converge, the result returned will not be precise (relative error "<<relErr<<", tolerance "<<relTol<<")");
-
-	Every log message is prepended filename, line number and function name; the final message that will appear will look like this::
-
-		237763 WARN  yade.ViscosityIterSolver /tmp/yade/trunk/extra/ViscosityIterSolver.cpp:316 newtonRaphsonSolve: Exceeded 30 steps in attempts to converge, the result returned will not be precise (relative error 5.2e-3, tolerance 1e-3)
-
-	The ``237763 WARN  yade.ViscosityIterSolver`` (microseconds from start, severity, logger name) is added by log4cxx and is completely configurable, either programatically, or by using file ``~/.yade-\$SUFFIX/logging.conf``, which is loaded at startup, if present (FIXME: see more etc user's guide)
-
-
-* special tracing macros ``TRVAR1``, ``TRVAR2``, … ``TRVAR6``, which show both variable name and its value (there are several more macros defined inside ``/lib/base/Logging.hpp``, but they are not generally in use):
-
-	.. code-block:: c++
-
-		TRVAR3(var1,var2,var3);
-		// will be expanded to:
-		LOG_TRACE("var1="<<var1<<"; var2="<<var2<<"; var3="<<var3);
-
-
-.. note:: For performance reasons, optimized builds eliminate ``LOG_TRACE`` and ``LOG_DEBUG`` from the code at preprocessor level.
-
-.. note:: Builds without log4cxx (even in debug mode) eliminate ``LOG_TRACE`` and ``LOG_DEBUG``. As there is no way to enable/disable them selectively, the log amount would be huge.
-
-Python provides rudimentary control for the logging system in ``yade.log`` module (FIXME: ref to docs):
-
-.. ipython::
-
-	Yade [2]: from yade import log
-
-	Yade [3]: log.setLevel('InsertionSortCollider',log.DEBUG)  # sets logging level of the yade.InsertionSortCollider logger
-
-	Yade [4]: log.setLevel('',log.WARN)                        # sets logging level of all yade.* loggers (they inherit level from the parent logger, except when overridden)
-
-As of now, there is no python interface for performing logging into log4cxx loggers themselves.
 
 .. _timing:
 
@@ -1211,12 +1153,12 @@
 	.. code-block:: c++
 		
 		// header file
-		class Law2_Dem3DofGeom_CpmPhys_Cpm: public LawFunctor {
+		class Law2_ScGeom_CpmPhys_Cpm: public LawFunctor {
 		   /* … */
-		   YADE_CLASS_BASE_DOC_ATTRS_CTOR(Law2_Dem3DofGeom_CpmPhys_Cpm,LawFunctor,"docstring",
+		   YADE_CLASS_BASE_DOC_ATTRS_CTOR(Law2_ScGeom_CpmPhys_Cpm,LawFunctor,"docstring",
 		      /* attrs */,
 		      /* constructor */
-		      timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas);
+		      timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas); // timingDeltas object is automatically initialized when using -DCMAKE_CXX_FLAGS="-DUSE_TIMING_DELTAS" cmake option
 		   );
 		   // ...
 		};
@@ -1228,7 +1170,7 @@
 
 	.. code-block:: c++
 
-		void Law2_Dem3DofGeom_CpmPhys_Cpm::go(shared_ptr<IGeom>& _geom,
+		void Law2_ScGeom_CpmPhys_Cpm::go(shared_ptr<IGeom>& _geom,
 		                                      shared_ptr<IPhys>& _phys,
 		                                      Interaction* I,
 		                                      Scene* scene)
@@ -1244,6 +1186,25 @@
 		   timingDeltas->checkpoint("rest");
 		}
 
+#. Alternatively, you can compile Yade using -DCMAKE_CXX_FLAGS="-DUSE_TIMING_DELTAS" cmake option and use predefined macros TIMING_DELTAS_START and TIMING_DELTAS_CHECKPOINT. Without -DUSE_TIMING_DELTAS options, those macros are empty and do nothing.
+	.. code-block:: c++
+
+		void Law2_ScGeom_CpmPhys_Cpm::go(shared_ptr<IGeom>& _geom,
+		                                      shared_ptr<IPhys>& _phys,
+		                                      Interaction* I,
+		                                      Scene* scene)
+		{
+		   TIMING_DELTAS_START();
+		   // prepare some variables etc here
+		   TIMING_DELTAS_CHECKPOINT("setup")
+		   // find geometrical data (deformations) here
+		   TIMING_DELTAS_CHECKPOINT("geom")
+		   // compute forces here
+		   TIMING_DELTAS_CHECKPOINT("material")
+		   // apply forces, cleanup here
+		   TIMING_DELTAS_CHECKPOINT("rest")
+		}
+
 The output might look like this (note that functors are nested inside dispatchers and ``TimingDeltas`` inside their engine/functor)::
 
 	Name                                    Count                 Time          Rel. time
@@ -1254,7 +1215,7 @@
 	IGeomDispatcher       400           15177607μs             14.87%      
 	IPhysDispatcher        400            9518738μs              9.33%      
 	LawDispatcher                       400           64810867μs             63.49%      
-	  Law2_Dem3DofGeom_CpmPhys_Cpm                                                     
+	  Law2_ScGeom_CpmPhys_Cpm                                                     
 	    setup                           4926145            7649131μs             15.25%  
 	    geom                            4926145           23216292μs             46.28%  
 	    material                        4926145            8595686μs             17.14%  
@@ -1593,7 +1554,7 @@
 Yade's main program is python script in :ysrc:`core/main/main.py.in`; the build system replaces a few ``\${variables}`` in that file before copying it to its install location. It does the following:
 
 #. Process command-line options, set environment variables based on those options.
-#. Import main yade module (``import yade``), residing in :ysrc:`py/__init__.py.in`. This module locates plugins (recursive search for files ``lib*.so`` in the ``lib`` installation directory). :ysrc:`yade.boot<core/main/pyboot.cpp>` module is used to setup logging, temporary directory, … and, most importantly, loads plugins.
+#. Import main yade module (``import yade``), residing in :ysrc:`py/__init__.py.in`. This module locates plugins (recursive search for files ``lib*.so`` in the ``lib`` installation directory). :ysrc:`yade.boot<core/main/pyboot.cpp>` module is used to setup temporary directory, … and, most importantly, loads plugins.
 #. Manage further actions, such as running scripts given at command line, opening :yref:`yade.qt.Controller` (if desired), launching the ``ipython`` prompt.
 
 
@@ -1735,7 +1696,7 @@
 
 .. [#wrap]
 	Wrapped classes are automatically registered when the class wrapper is created. If wrapped class derives from another wrapped class (and if this dependency is declared with the ``boost::python::bases`` template, which Yade's classes do automatically), parent class must be registered before derived class, however. (This is handled via loop in ``Omega::buildDynlibDatabase``, which reiterates over classes, skipping failures, until they all successfully register)
-	Math classes (Vector3, Matrix3, Quaternion) are wrapped by hand, to be found in :ysrc:`py/mathWrap/miniEigen.cpp`; this module is imported at startup.
+	Math classes (Vector3, Matrix3, Quaternion) are wrapped by hand, to be found in :ysrc:`py/mathWrap/miniEigen.cpp`; this module is imported at startup. On systems, where minieigen is available as a separate package, the Yade's miniEigen is skipped.
 
 
 Maintaining compatibility

=== modified file 'doc/sphinx/templates/index.html'
--- doc/sphinx/templates/index.html	2012-03-30 13:43:58 +0000
+++ doc/sphinx/templates/index.html	2013-02-26 19:28:47 +0000
@@ -1,7 +1,7 @@
 {% extends "layout.html" %}
 {% set title = 'Overview' %}
 {% block body %}
-  <h1>Welcome to Yade</h1>
+  <h1>Welcome to Yade - Open Source Discrete Element Method</h1>
   <p>
 	Yade is an extensible open-source framework for discrete numerical models, focused on Discrete Element Method. The computation parts are written in c++ using flexible object model, allowing independent implementation of new alogrithms and interfaces. Python is used for rapid and concise scene construction, simulation control, postprocessing and debugging.
   <p>

=== modified file 'doc/sphinx/tutorial-data-mining.rst'
--- doc/sphinx/tutorial-data-mining.rst	2011-01-20 16:35:46 +0000
+++ doc/sphinx/tutorial-data-mining.rst	2013-03-05 10:48:14 +0000
@@ -54,9 +54,9 @@
 	Yade [1]: from yade import *
 	
 	Yade [1]: O.engines=[
-	     ...:    NewtonIntegrator(damping=.2,label='newton')
-	     ...: ]
-	     ...:
+	   ...:    NewtonIntegrator(damping=.2,label='newton')
+	   ...: ]
+	   ...:
 
 	Yade [1]: newton.damping=.4
 

=== modified file 'doc/sphinx/tutorial-hands-on.rst'
--- doc/sphinx/tutorial-hands-on.rst	2012-09-08 01:19:45 +0000
+++ doc/sphinx/tutorial-hands-on.rst	2013-03-21 19:28:57 +0000
@@ -250,15 +250,15 @@
 	Yade [2]: a=3.1
 
 	Yade [3]: if a<pi: b=0           # conditional statement
-	     ...: else: b=1
-		  ...:
+	   ...: else: b=1
+	   ...:
 
 	Yade [4]: c=0 if a<1 else 1      # conditional expression
 
 	Yade [5] b,c:
 
 	Yade [1]: def square(x): return x**2    # define a new function
-	     ...:
+	   ...:
 
 	Yade [1]: square(2)                     # and call that function
 
@@ -353,14 +353,10 @@
 	Yade [1]: sp.makeCloud((1,1,1),(2,2,2),rMean=.2) # put spheres with defined radius inside box given by corners (1,1,1) and (2,2,2)
 
 	Yade [1]: for c,r in sp: print c,r               # print center and radius of all particles (SpherePack is a sequence which can be iterated over)
-	     ...:
+	   ...:
 
 	Yade [1]: sp.toSimulation()                      # create particles and add them to the simulation
 
-.. note::
-
-	:yref:`Vector3<external:miniEigen.Vector3>` is class representing 3D vector; a number of geometry operations are supported by :yref:`Vector3<external:miniEigen.Vector3>`, such as scalar product, dot product, cross product, norm, addition and more. There are other similar classes such as :yref:`Vector2<external:miniEigen.Vector2>`, :yref:`Matrix3<external:miniEigen.Matrix3>` (3×3 matrix), :yref:`Quaterion<external:miniEigen.Quaternion>`, :yref:`Vector6<external:miniEigen.Vector6>` etc. See :yref:`miniEigen<external:miniEigen>` module documentation for details.
-
 Boundaries
 """"""""""
 
@@ -423,16 +419,16 @@
 	Yade [1]: O.reset()
 
 	Yade [1]: 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(),Ig2_Wall_Sphere_L3Geom()],
-	     ...:        [Ip2_FrictMat_FrictMat_FrictPhys()],
-	     ...:        [Law2_L3Geom_FrictPhys_ElPerfPl()]
-	     ...:    ),
-	     ...:    NewtonIntegrator(damping=.2,label='newton')      # define a name under which we can access this engine easily
-	     ...: ]
-	     ...:
+	   ...:    ForceResetter(),
+	   ...:    InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Wall_Aabb()]),
+	   ...:    InteractionLoop(           # dtto for the parenthesis here
+	   ...:        [Ig2_Sphere_Sphere_L3Geom(),Ig2_Wall_Sphere_L3Geom()],
+	   ...:        [Ip2_FrictMat_FrictMat_FrictPhys()],
+	   ...:        [Law2_L3Geom_FrictPhys_ElPerfPl()]
+	   ...:    ),
+	   ...:    NewtonIntegrator(damping=.2,label='newton')      # define a name under which we can access this engine easily
+	   ...: ]
+	   ...:
 
 	Yade [1]: O.engines
 

=== modified file 'doc/sphinx/tutorial/06-periodic-triaxial-test.py'
--- doc/sphinx/tutorial/06-periodic-triaxial-test.py	2011-01-30 15:43:18 +0000
+++ doc/sphinx/tutorial/06-periodic-triaxial-test.py	2013-03-08 15:05:59 +0000
@@ -29,6 +29,8 @@
 
 # generate loose packing
 from yade import pack, qt, plot
+
+O.periodic=True
 sp=pack.SpherePack()
 if 0:
 	## uniform distribution
@@ -40,9 +42,9 @@
 else:
 	## create packing from clumps
 	# configuration of one clump
-	c1=pack.SpherePack([((0,0,0),.1),((.15,0,0),.05),((0,.1,0),.05)])
+	c1=pack.SpherePack([((0,0,0),.03333),((.03,0,0),.017),((0,.03,0),.017)])
 	# make cloud using the configuration c1 (there could c2, c3, ...; selection between them would be random)
-	sp.makeClumpCloud((0,0,0),(2,2,2),[c1],periodic=True)
+	sp.makeClumpCloud((0,0,0),(2,2,2),[c1],periodic=True,num=500)
 
 # setup periodic boundary, insert the packing
 sp.toSimulation()
@@ -51,21 +53,21 @@
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb()]),
 	InteractionLoop(
-		[Ig2_Sphere_Sphere_L3Geom()],
+		[Ig2_Sphere_Sphere_ScGeom()],
 		[Ip2_FrictMat_FrictMat_FrictPhys()],
-		[Law2_L3Geom_FrictPhys_ElPerfPl()]
+		[Law2_ScGeom_FrictPhys_CundallStrack()]
 	),
-	NewtonIntegrator(damping=.6),
 	PeriTriaxController(label='triax',
 		# specify target values and whether they are strains or stresses
 		goal=(sigmaIso,sigmaIso,sigmaIso),stressMask=7,
 		# type of servo-control
-		dynCell=True,maxStrainRate=(.1,.1,.1),
+		dynCell=True,maxStrainRate=(10,10,10),
 		# wait until the unbalanced force goes below this value
 		maxUnbalanced=.1,relStressTol=1e-3,
 		# call this function when goal is reached and the packing is stable
 		doneHook='compactionFinished()'
 	),
+	NewtonIntegrator(damping=.2),
 	PyRunner(command='addPlotData()',iterPeriod=100),
 ]
 O.dt=.5*utils.PWaveTimeStep()

=== modified file 'doc/sphinx/user.rst'
--- doc/sphinx/user.rst	2012-09-08 01:19:45 +0000
+++ doc/sphinx/user.rst	2013-05-14 20:32:05 +0000
@@ -66,16 +66,16 @@
 	@suppress
 	Yade [0]: O.reset()
 
-	Yade [1]: O.bodies.append(utils.sphere((0,0,0),1))
+	Yade [1]: O.bodies.append(utils.sphere((0,10,0),1))
 
 	Yade [2]: O.bodies.append(utils.sphere((0,0,2),1))
 
 	# this is the same, but in one function call
 
 	Yade [3]: O.bodies.append([
-	     ...:    utils.sphere((0,0,0),1),
-		  ...:    utils.sphere((0,0,2),1)
-		  ...: ])
+	   ...:   utils.sphere((0,0,0),1),
+	   ...:   utils.sphere((0,0,2),1)
+	   ...: ])
 
 Many functions introduced in next sections return list of bodies which can be readily added to the simulation, including
 
@@ -89,7 +89,16 @@
 Clumping particles together
 ----------------------------
 
-In some cases, you might want to create rigid aggregate of individual particles (i.e. particles will retain their mutual position during simulation); a special function :yref:`BodyContainer.appendClumped` is designed for this task; for instance, we might add 2 spheres tied together:
+In some cases, you might want to create rigid aggregate of individual particles (i.e. particles will retain their mutual position during simulation). This we call a :yref:`clump<Clump>`. 
+A clump is internally represented by a special :yref:`body<Body>`, referenced by :yref:`clumpId<Body.clumpId>` of its members (see also  :yref:`isClump<Body.isClump>`, :yref:`isClumpMember<Body.isClumpMember>` and :yref:`isStandalone<Body.isStandalone>`). 
+Like every body a clump has a :yref:`position<State.pos>`, which is the balance point between all members. 
+A clump body itself has no :yref:`interactions<Interaction>` with other bodies. Interactions between clumps is internally represented by interactions between clump members. There are also no interactions between clump members with same clumpId. 
+
+YADE supports different ways of creating clumps:
+
+* Create clumps and spheres (clump members) directly with one command:
+
+The function :yref:`appendClumped()<BodyContainer.appendClumped>` is designed for this task. For instance, we might add 2 spheres tied together:
 
 .. ipython::
 
@@ -97,9 +106,9 @@
 	Yade [0]: O.reset()
 
 	Yade [1]: O.bodies.appendClumped([
-	     ...:    utils.sphere([0,0,0],1),
-		  ...:    utils.sphere([0,0,2],1)
-		  ...: ])
+	   ...:    utils.sphere([0,0,0],1),
+	   ...:    utils.sphere([0,0,2],1)
+	   ...: ])
 
 	Yade [2]: len(O.bodies)
 
@@ -107,8 +116,38 @@
 
 	Yade [2]: O.bodies[2].isClump, O.bodies[2].clumpId
 	
-
-:yref:`appendClumped<BodyContainer.appendClumped>` returns a tuple of ``(clumpId,[memberId1,memberId2])``: clump is internally represented by a special :yref:`Body`, referenced by :yref:`clumpId<Body.clumpId>` of its members (see also  :yref:`isClump<Body.isClump>`, :yref:`isClumpMember<Body.isClumpMember>` and :yref:`isStandalone<Body.isStandalone>`).
+-> :yref:`appendClumped()<BodyContainer.appendClumped>` returns a tuple of ids ``(clumpId,[memberId1,memberId2,...])``
+
+* Use existing spheres and clump them together:
+
+For this case the function :yref:`clump()<BodyContainer.clump>` can be used. One way to do this is to create a list of bodies, that should be clumped before using the :yref:`clump()<BodyContainer.clump>` command:
+
+.. ipython::
+
+	@suppress
+	Yade [0]: O.reset()
+
+	Yade [1]: bodyList = []
+
+	Yade [2]: for ii in range(0,5):
+	   ...:    bodyList.append(O.bodies.append(utils.sphere([ii,0,1],.5)))#create a "chain" of 5 spheres
+	   ...:
+
+	Yade [3]: print bodyList
+
+	Yade [4]: idClump=O.bodies.clump(bodyList)
+	
+-> :yref:`clump()<BodyContainer.clump>` returns ``clumpId``
+
+* Another option is to replace :yref:`standalone<Body.isStandalone>` spheres from a given packing (see :yref:`SpherePack<yade._packSpheres.SpherePack>` and :yref:`makeCloud<yade._packSpheres.SpherePack.makeCloud>`) using clump templates.
+
+This is done by a function called :yref:`replaceByClumps()<BodyContainer.replaceByClumps>`. This function takes a list of :yref:`clumpTemplates()<yade.utils.clumpTemplate>` and a list of amounts and replaces spheres by clumps. The volume of a new clump will be the same as the volume of the sphere, that was replaced (clump volume/mass/inertia is accounting for overlaps assuming that there are only pair overlaps).
+
+-> :yref:`replaceByClumps()<yade.wrapper.BodyContainer.replaceByClumps>` returns a list of tuples: ``[(clumpId1,[memberId1,memberId2,...]),(clumpId2,[memberId1,memberId2,...]),...]``
+
+It is also possible to :yref:`add<BodyContainer.addToClump>` bodies to a clump and :yref:`release<BodyContainer.releaseFromClump>` bodies from a clump. Also you can :yref:`erase<BodyContainer.erase>` the clump (clump members will get standalone spheres).
+
+.. note:: Have a look at ``examples/clumps/`` folder. There you will find some examples, that show usage of different functions for clumps.
 
 Sphere packings
 ===============
@@ -374,14 +413,14 @@
 
 In typical cases, interactions are created during simulations as particles collide. This is done by a :yref:`Collider` detecting approximate contact between particles and then an :yref:`IGeomFunctor` detecting exact collision.
 
-Some material models (such as the :yref:`concrete model<Law2_Dem3DofGeom_CpmPhys_Cpm>`) rely on initial interaction network which is denser than geometrical contact of spheres: sphere's radii as "enlarged" by a dimensionless factor called *interaction radius* (or *interaction ratio*) to create this initial network. This is done typically in this way (see :ysrc:`examples/concrete/uniax.py` for an example):
+Some material models (such as the :yref:`concrete model<Law2_ScGeom_CpmPhys_Cpm>`) rely on initial interaction network which is denser than geometrical contact of spheres: sphere's radii as "enlarged" by a dimensionless factor called *interaction radius* (or *interaction ratio*) to create this initial network. This is done typically in this way (see :ysrc:`examples/concrete/uniax.py` for an example):
 
 #. Approximate collision detection is adjusted so that approximate contacts are detected also between particles within the interaction radius. This consists in setting value of :yref:`Bo1_Sphere_Aabb.aabbEnlargeFactor` to the interaction radius value.
 
 #. The geometry functor (``Ig2``)
    would normally say that "there is no contact" if given 2 spheres that are not in contact. Therefore, the same value as for :yref:`Bo1_Sphere_Aabb.aabbEnlargeFactor` must be given to it. (Either :yref:`Ig2_Sphere_Sphere_Dem3DofGeom.distFactor` or :yref:`Ig2_Sphere_Sphere_ScGeom.interactionDetectionFactor`, depending on the functor that is in use.
 
-   Note that only :yref:`Sphere` + :yref:`Sphere` interactions are supported; there is no parameter analogous to :yref:`distFactor<Ig2_Sphere_Sphere_Dem3DofGeom.distFactor>` in :yref:`Ig2_Facet_Sphere_Dem3DofGeom`. This is on purpose, since the interaction radius is meaningful in bulk material represented by sphere packing, whereas facets usually represent boundary conditions which should be exempt from this dense interaction network.
+   Note that only :yref:`Sphere` + :yref:`Sphere` interactions are supported; there is no parameter analogous to :yref:`distFactor<Ig2_Sphere_Sphere_ScGeom.interactionDetectionFactor>` in :yref:`Ig2_Facet_Sphere_ScGeom`. This is on purpose, since the interaction radius is meaningful in bulk material represented by sphere packing, whereas facets usually represent boundary conditions which should be exempt from this dense interaction network.
 
 #. Run one single step of the simulation so that the initial network is created.
 
@@ -403,11 +442,11 @@
 	   InteractionLoop(
 	      [
 	         # enlarge here
-	         Ig2_Sphere_Sphere_Dem3DofGeom(distFactor=intRadius,label='ig2ss'),
-	         Ig2_Facet_Sphere_Dem3DofGeom(),
+	         Ig2_Sphere_Sphere_ScGeom(interactionDetectionFactor=intRadius,label='ig2ss'),
+	         Ig2_Facet_Sphere_ScGeom(),
 	      ],
 	      [Ip2_CpmMat_CpmMat_CpmPhys()],
-	      [Law2_Dem3DofGeom_CpmPhys_Cpm(epsSoft=0)], # deactivated
+	      [Law2_ScGeom_CpmPhys_Cpm(epsSoft=0)], # deactivated
 	   ),
 	   NewtonIntegrator(damping=damping,label='damper'),
 	]
@@ -416,9 +455,8 @@
 	O.step()
 
 	# reset interaction radius to the default value
-	# see documentation of those attributes for the meaning of negative values
-	bo1s.aabbEnlargeFactor=-1
-	ig2ss.distFactor=-1
+	bo1s.aabbEnlargeFactor=1.0
+	ig2ss.interactionDetectionFactor=1.0
 
 	# now continue simulation
 	O.run()
@@ -436,18 +474,18 @@
 	Yade [1]: O.materials.append(FrictMat(young=3e10,poisson=.2,density=1000))
 
 	Yade [1]: O.bodies.append([
-	     ...:    utils.sphere([0,0,0],1),
-	     ...:    utils.sphere([0,0,1000],1)
-	     ...: ])
+	   ...:    utils.sphere([0,0,0],1),
+	   ...:    utils.sphere([0,0,1000],1)
+	   ...: ])
 
 	# only add InteractionLoop, no other engines are needed now
 	Yade [1]: O.engines=[
-	     ...:    InteractionLoop(
-	     ...:        [Ig2_Sphere_Sphere_Dem3DofGeom(),],
-	     ...:        [Ip2_FrictMat_FrictMat_FrictPhys()],
-	     ...:        [] # not needed now
-	     ...:    )
-	     ...: ]
+	   ...:    InteractionLoop(
+	   ...:        [Ig2_Sphere_Sphere_ScGeom(),],
+	   ...:        [Ip2_FrictMat_FrictMat_FrictPhys()],
+	   ...:        [] # not needed now
+	   ...:    )
+	   ...: ]
 
 	Yade [1]: i=utils.createInteraction(0,1)
 
@@ -492,6 +530,9 @@
 
 	O.engines=O.engines[:2]+[SomeEngine()]+O.engines[2:]
 
+.. note::
+	When Yade starts, O.engines is filled with a reasonable default list, so that it is not strictly necessary to redefine it when trying simple things. The default scene will handle spheres, boxes, and facets with :yref:`frictional<FrictMat>` properties correctly, and adjusts the timestep dynamically. You can find an example in simple-scene-default-engines.py.
+
 Functors choice
 ----------------
 
@@ -524,23 +565,23 @@
 #. shape combinations that should collide;
    for instance::
 
-      InteractionLoop([Ig2_Sphere_Sphere_Dem3DofGeom()],[],[])
+      InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[],[])
 
    will handle collisions for :yref:`Sphere` + :yref:`Sphere`, but not for :yref:`Facet` + :yref:`Sphere` -- if that is desired, an additional functor must be used::
    
       InteractionLoop([
+         Ig2_Sphere_Sphere_ScGeom(),
+         Ig2_Facet_Sphere_ScGeom()
+      ],[],[])
+   
+   Again, missing combination will cause given shape combinations to freely interpenetrate one another.
+
+#. :yref:`IGeom` type accepted by the ``Law2`` functor (below); it is the first part of functor's name after ``Law2`` (for instance, :yref:`Law2_ScGeom_CpmPhys_Cpm` accepts :yref:`ScGeom`). This is (for most cases) either :yref:`Dem3DofGeom` (total shear formulation) or :yref:`ScGeom` (incremental shear formulation). For :yref:`Dem3DofGeom`, the above example would simply change to::
+
+      InteractionLoop([
          Ig2_Sphere_Sphere_Dem3DofGeom(),
          Ig2_Facet_Sphere_Dem3DofGeom()
       ],[],[])
-   
-   Again, missing combination will cause given shape combinations to freely interpenetrate one another.
-
-#. :yref:`IGeom` type accepted by the ``Law2`` functor (below); it is the first part of functor's name after ``Law2`` (for instance, :yref:`Law2_Dem3DofGeom_CpmPhys_Cpm` accepts :yref:`Dem3DofGeom`). This is (for most cases) either :yref:`Dem3DofGeom` (total shear formulation) or :yref:`ScGeom` (incremental shear formulation). For :yref:`ScGeom`, the above example would simply change to::
-
-      InteractionLoop([
-         Ig2_Sphere_Sphere_ScGeom(),
-         Ig2_Facet_Sphere_ScGeom()
-      ],[],[])
 
 Ip2 functors
 ^^^^^^^^^^^^
@@ -562,6 +603,8 @@
 
 .. note:: As in the case of ``Ip2`` functors, receiving a combination of :yref:`IGeom` and :yref:`IPhys` which is not handled by any ``Law2`` functor is an error.
 
+.. warning:: Many ``Law2`` exist in Yade, and new ones can appear at any time. In some cases different functors are only different implementations of the same contact law (e.g. :yref:`Law2_ScGeom_FrictPhys_CundallStrack` and :yref:`Law2_L3Geom_FrictPhys_ElPerfPl`). Also, sometimes, the peculiarity of one functor may be reproduced as a special case of a more general one. Therefore, for a given constitutive behavior, the user may have the choice between different functors. It is strongly recommended to favor the most used and most validated implementation when facing such choice. A list of available functors classified from mature to unmaintained is updated `here <https://yade-dem.org/wiki/ConstitutiveLaws`_ to guide this choice.
+
 Examples
 ^^^^^^^^
 
@@ -585,18 +628,18 @@
 
 Concrete model
 ^^^^^^^^^^^^^^^
-In this case, our goal is to use the :yref:`Law2_Dem3DofGeom_CpmPhys_Cpm` constitutive law.
+In this case, our goal is to use the :yref:`Law2_ScGeom_CpmPhys_Cpm` constitutive law.
 
-* We use :yref:`spheres<Sphere>` and :yref:`facets<Facet>` in the simulation, which selects ``Ig2`` functors accepting those types and producing :yref:`Dem3DofGeom`: :yref:`Ig2_Sphere_Sphere_Dem3DofGeom` and :yref:`Ig2_Facet_Sphere_Dem3DofGeom`.
+* We use :yref:`spheres<Sphere>` and :yref:`facets<Facet>` in the simulation, which selects ``Ig2`` functors accepting those types and producing :yref:`ScGeom`: :yref:`Ig2_Sphere_Sphere_ScGeom` and :yref:`Ig2_Facet_Sphere_ScGeom`.
 
 * We have to use :yref:`Material` which can be used for creating :yref:`CpmPhys`. We find that :yref:`CpmPhys` is only  created by :yref:`Ip2_CpmMat_CpmMat_CpmPhys`, which determines the choice of :yref:`CpmMat` for all particles.
 
 Therefore, we will use::
 
    InteractionLoop(
-      [Ig2_Sphere_Sphere_Dem3DofGeom(),Ig2_Facet_Sphere_Dem3DofGeom()],
+      [Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom()],
       [Ip2_CpmMat_CpmMat_CpmPhys()],
-      [Law2_Dem3DofGeom_CpmPhys_Cpm()]
+      [Law2_ScGeom_CpmPhys_Cpm()]
    )
 
 
@@ -949,9 +992,9 @@
 .. ipython::
 	
 	Yade [1]: plot.plots={
-	     ...:    'i':('t',),
-	     ...:    'i':('z1','v1')
-	     ...: }
+	   ...:    'i':('t',),
+	   ...:    'i':('z1','v1')
+	   ...: }
 
 	Yade [2]: plot.plots
 
@@ -960,9 +1003,9 @@
 .. ipython::
 	
 	Yade [1]: plot.plots={
-	     ...:    'i':('t',),
-	     ...:    'i ':('z1','v1') # note the space in 'i '
-	     ...: }
+	   ...:    'i':('t',),
+	   ...:    'i ':('z1','v1') # note the space in 'i '
+	   ...: }
 
 	Yade [2]: plot.plots
 
@@ -976,7 +1019,9 @@
 Exporting
 ^^^^^^^^^
 
-Plots can be exported to external files for later post-processing via that :yref:`yade.plot.saveGnuplot` function.
+Plots can be exported to external files for later post-processing via that :yref:`yade.plot.saveGnuplot` function. Note that all data you added via plot.addData is saved - even data that you don't plot live during simulation. 
+By editing the generated .gnuplot file you can plot any of the added Data afterwards.
+
 
 * Data file is saved (compressed using bzip2) separately from the gnuplot file, so any other programs can be used to process them. In particular, the ``numpy.genfromtxt`` (documented `here <http://docs.scipy.org/doc/numpy/reference/generated/numpy.genfromtxt.html>`_) can be useful to import those data back to python; the decompression happens automatically.
 
@@ -1009,7 +1054,7 @@
 	def checkUnbalanced():
 		if utils.unbalancedForce<1e-2: O.pause()
 
-	O.engines=O.engines+[PyRunner(command="checkUnbalanced",iterPeriod=100)]
+	O.engines=O.engines+[PyRunner(command="checkUnbalanced()",iterPeriod=100)]
 
 	# this would work as well, without the function defined apart:
 	#   PyRunner(command="if utils.unablancedForce<1e-2: O.pause()",iterPeriod=100)
@@ -1089,7 +1134,7 @@
 --------------
 ``TCP python prompt`` is telnet server with authenticated connection, providing full python command-line. It listens on port 9000, or higher if already occupied (by another yade instance, for example).
 
-Using the authentication cookie, connection can be made::
+Using the authentication cookie, connection can be made using telnet::
 
 	\$ telnet localhost 9000
 	Trying 127.0.0.1...
@@ -1111,7 +1156,7 @@
 #. The (fake) ``>>>`` interpreter does not have rich interactive feature of IPython, which handles the usual command-line ``Yade [1]:``; therefore, you will have no command history, ``?`` help and so on.
 
 .. note::
-	By giving access to python interpreter, full control of the system (including reading user's files) is possible. For this reason, **connection are only allowed from localhost**, not over network remotely.
+	By giving access to python interpreter, full control of the system (including reading user's files) is possible. For this reason, **connection are only allowed from localhost**, not over network remotely. Of course you can log into the system via SSH over network to get remote access.
 
 .. warning::
 	Authentication cookie is trivial to crack via bruteforce attack. Although the listener stalls for 5 seconds after every failed login attempt (and disconnects), the cookie could be guessed by trial-and-error during very long simulations on a shared computer.
@@ -1133,20 +1178,18 @@
 	:yref:`yade.utils.readParamsFromTable` knows which parameter file and which line to read by inspecting the ``PARAM_TABLE`` environment variable, set by the batch system.
 
 parameter table
-	simple text file, each line representing one parameter set. This file is read by :yref:`yade.utils.readParamsFromTable` (using :yref:`yade.utils.TableParamReader` class), called from simulation script, as explained above.
+	simple text file, each line representing one parameter set. This file is read by :yref:`yade.utils.readParamsFromTable` (using :yref:`yade.utils.TableParamReader` class), called from simulation script, as explained above. For better reading of the text file you can make use of tabulators, these will be ignored by :yref:`yade.utils.readParamsFromTable`. Parameters are not restricted to numerical values. You can also make use of strings by "quoting" them ('  ' may also be used instead of "  "). This can be useful for nominal parameters.
 
 The batch can be run as ::
 
 	yade-batch parameters.table simulation.py
 
-and it will intelligently run one simulation for each parameter table line.
+and it will intelligently run one simulation for each parameter table line. A minimal example is found in :ysrc:`examples/test/batch/params.table` and :ysrc:`examples/test/batch/sim.py`, another example follows.
 
 Example
 --------
 
-This example is found in :ysrc:`scripts/batch.table` and :ysrc:`scripts/batch.py`.
-
-Suppsoe we want to study influence of parameters *density* and *initialVelocity* on position of a sphere falling on fixed box. We create parameter table like this::
+Suppose we want to study influence of parameters *density* and *initialVelocity* on position of a sphere falling on fixed box. We create parameter table like this::
 
  description density initialVelocity # first non-empty line are column headings
  reference   2400    10
@@ -1225,7 +1268,7 @@
 
 Separating output files from jobs
 ----------------------------------
-As one might output data to external files during simulation (using classes such as :yref:`VTKRecorder`, it is important to name files in such way that they are not overwritten by next (or concurrent) job in the same batch. A special tag ``O.tags['id']`` is provided for such purposes: it is comprised of date, time and PID, which makes it always unique (e.g. ``20100413T144723p7625``); additional advantage is that alphabetical order of the ``id`` tag is also chronological.
+As one might output data to external files during simulation (using classes such as :yref:`VTKRecorder`, it is important to name files in such way that they are not overwritten by next (or concurrent) job in the same batch. A special tag ``O.tags['id']`` is provided for such purposes: it is comprised of date, time and PID, which makes it always unique (e.g. ``20100413T144723p7625``); additional advantage is that alphabetical order of the ``id`` tag is also chronological. To add the used parameterset or if set the description of the job you could add O.tags['params'] to the filename.
 
 For smaller simulations, prepending all output file names with ``O.tags['id']`` can be sufficient:
 
@@ -1268,7 +1311,7 @@
 
 	print 'gnuplot',plot.saveGnuplot(O.tags['id'])
 
-and the end of the script, which prints::
+and the end of the script (even after utils.waitIfBatch()) , which prints::
 
 	gnuplot 20100413T144723p7625.gnuplot
 
@@ -1355,8 +1398,8 @@
 .. _img-paraview-rendering-apply:
 .. figure:: fig/paraview-rendering-apply.png
 
-Rendering spherical particles
-"""""""""""""""""""""""""""""
+Rendering spherical particles. Glyphs
+"""""""""""""""""""""""""""""""""""""""""""
 
 .. |paraview-glyph-icon| image:: fig/paraview-glyph-icon.png
 
@@ -1370,6 +1413,19 @@
 
 After clicking "Apply", spheres will appear. They will be rendered over the original white points, which you can disable by clicking on the eye icon next to ``p1-spheres.*`` in the Pipeline browser.
 
+Rendering spherical particles. PointSprite
+"""""""""""""""""""""""""""""""""""""""""""
+
+Another opportunity to display spheres is an using *PointSprite* plugin. This technique requires much less RAM in comparison to Glyphs.
+
+* "Tools -> Manage Plugins"
+* "PointSprite_Plugin -> Load selected  -> Close"
+* Load VTU-files
+* "Representation -> Point Sprite"
+* "Point Sprite -> Scale By -> radii"
+* "Edit Radius Transfer Function -> Proportional -> Multiplier = 1.0 -> Close"
+
+
 Facet transparency
 """""""""""""""""""
 If you want to make facet objects transparent, select ``p1-facets.*`` in the Pipeline browser, then go to the Object inspector on the Display tab. Under "Style", you can set the "Opacity" value to something smaller than 1.
@@ -1383,9 +1439,32 @@
 Python specialties and tricks
 ******************************
 
+Importing Yade in other Python applications
+===========================================
+Yade can be imported in other Python applications. To do so, you need somehow to make yade executable .py extended. The easiest way is to create a symbolic link, i.e. (suppose your Yade executable file is called "yade-trunk" and you want make it "yadeimport.py"):
+
+.. code-block:: console
+	
+	\$ cd /path/where/you/want/yadeimport
+	\$ ln -s /path/to/yade/executable/yade-trunk yadeimport.py
+
+Then you need to make your yadeimport.py findable by Python. You can export PYTHONPATH environment variable, or simply use sys.path directly in Python script:
+
+.. code-block:: python
+
+	import sys
+	sys.path.append('/path/where/you/want/yadeimport')
+	from yadeimport import *
+
+	print Matrix3(1,2,3, 4,5,6, 7,8,9)
+	print O.bodies
+	# any other Yade code
+
 .. perhaps turn this section into a list of FAQs on python as gathered from the yade-users list?
 
 
+
+
  
 
 **************

=== modified file 'doc/sphinx/yadeSphinx.py'
--- doc/sphinx/yadeSphinx.py	2012-10-31 18:43:29 +0000
+++ doc/sphinx/yadeSphinx.py	2013-03-21 19:28:57 +0000
@@ -210,14 +210,16 @@
 global writer
 writer=None
 
-for w in ['html','latex']: #['html','latex']:
-	if 'nolatex' in sys.argv and w=='latex': continue # skip latex build if passed nolatex (used in debian packages)
+for w in ['html','latex','epub']:
 	writer=w
 	genWrapperRst()
 	# HACK: must rewrite sys.argv, since reference generator in conf.py determines if we output latex/html by inspecting it
 	sys.argv=['sphinx-build','-a','-E','-b','%s'%writer,'-d',outDir+'/doctrees','.',outDir+'/%s'%writer]
 	sphinx.main(sys.argv)
-	makeBaseClassesClickable((outDir+'/html/yade.wrapper.html' if writer=='html' else outDir+'/latex/Yade.tex'),writer)
+	if writer=='html':
+		makeBaseClassesClickable((outDir+'/html/yade.wrapper.html'),writer)
+	elif writer=='latex':
+		makeBaseClassesClickable((outDir+'/latex/Yade.tex'),writer)
 	if (os.path.exists('/usr/share/javascript/jquery/jquery.js')): #Check, whether jquery.js installed in system
 		os.system('rm '+ outDir+'/html/_static/jquery.js')
 		os.system('ln -s /usr/share/javascript/jquery/jquery.js '+ outDir+'/html/_static/jquery.js')

=== modified file 'doc/yade-articles.bib'
--- doc/yade-articles.bib	2012-10-15 10:34:55 +0000
+++ doc/yade-articles.bib	2013-05-03 16:45:52 +0000
@@ -347,3 +347,141 @@
   doi = {10.1002/nag.1109}
 }
 
+@article{Tong2012,
+	author = {{Tong, A.-T.} and {Catalano, E.} and {Chareyre, B.}},
+	title = {Pore-Scale Flow Simulations: Model Predictions Compared with Experiments on Bi-Dispersed Granular Assemblies},
+	doi= {10.2516/ogst/2012032},
+	url= {http://dx.doi.org/10.2516/ogst/2012032},
+	journal = {Oil & Gas Science and Technology - Rev. IFP Energies nouvelles},
+	year = {2012}
+}
+
+@article{Tran2012a,
+  title={An Algorithm for the Propagation of Uncertainty in Soils using the Discrete Element Method},
+  author={Tran, V.D.H. and Meguid, M.A. and Chouinard, L.E.},
+  journal = {The Electronic Journal of Geotechnical Engineering},
+  url={http://www.ejge.com/2012/Ppr12.283alr.pdf},
+  year=  {2012}
+}
+
+@article{Boon2012,
+	title = {A new algorithm for contact detection between convex polygonal and polyhedral particles in the discrete element method},
+	journal = {Computers and Geotechnics},
+	volume = {44},
+	number = {0},
+	pages = {73 - 82},
+	year = {2012},
+	doi = {10.1016/j.compgeo.2012.03.012},
+	url = {http://www.sciencedirect.com/science/article/pii/S0266352X12000535},
+	author = {C.W. Boon and G.T. Houlsby and S. Utili}
+}
+
+@article {Hartong2012a,
+	author = {Harthong, Barthélémy and Scholtès, Luc and Donzé, Frédéric-Victor},
+	title = {Strength characterization of rock masses, using a coupled DEM–DFN model},
+	journal = {Geophysical Journal International},
+	volume = {191},
+	number = {2},
+	url = {http://dx.doi.org/10.1111/j.1365-246X.2012.05642.x},
+	doi = {10.1111/j.1365-246X.2012.05642.x},
+	pages = {467--480},
+	year = {2012}
+}
+
+@Article{ Harthong2012b,
+	title = {Contact impingement in packings of elastic–plastic spheres, application to powder compaction},
+	journal = {International Journal of Mechanical Sciences},
+	volume = {61},
+	number = {1},
+	pages = {32–43},
+	year = {2012},
+	author = {Barthélémy Harthong and Jean-François Jérier and Vincent Richefeu and Bruno Chareyre and Pierre Dorémus and Didier Imbault and Frédéric-Victor Donzé}
+}
+
+@article{Puckett2011,
+  title = {Local origins of volume fraction fluctuations in dense granular materials},
+  author = {Puckett, James G. and Lechenault, Frédéric and Daniels, Karen E.},
+  journal = {Phys. Rev. E},
+  volume = {83},
+  issue = {4},
+  pages = {041301},
+  numpages = {8},
+  year = {2011},
+  month = {Apr},
+  doi = {10.1103/PhysRevE.83.041301},
+  url = {http://link.aps.org/doi/10.1103/PhysRevE.83.041301},
+}
+
+@article{Chen2012,
+	author = {Chen, Jingsong and Huang, Baoshan and Chen, Feng and Shu, Xiang},
+	title = {Application of discrete element method to Superpave gyratory compaction},
+	journal = {Road Materials and Pavement Design},
+	volume = {13},
+	number = {3},
+	pages = {480-500},
+	year = {2012},
+	doi = {10.1080/14680629.2012.694160},
+	URL = {http://www.tandfonline.com/doi/abs/10.1080/14680629.2012.694160}
+}
+
+@article{Nicot2013,
+	title={Second-order work analysis for granular materials using a multiscale approach},
+	author={Nicot, François and Hadda, Nejib and Darve, Félix},
+	journal={International Journal for Numerical and Analytical Methods in Geomechanics},
+	year={2013},
+	doi={10.1002/nag.2175}
+}
+
+@article{Tran2013,
+	title={A finite--discrete element framework for the 3D modeling of geogrid--soil interaction under pullout loading conditions},
+	author={Tran, VDH and Meguid, MA and Chouinard, LE},
+	journal={Geotextiles and Geomembranes},
+	volume={37},
+	pages={1-9},
+	year={2013},
+	publisher={Elsevier},
+	doi = {10.1016/j.geotexmem.2013.01.003}
+}
+
+@article{Tran2012c,
+	title={Discrete Element and Experimental Investigations of the Earth Pressure Distribution on Cylindrical Shafts},
+	author={Tran, Viet DH and Meguid, Mohamed A and Chouinard, Luc E},
+	journal={International Journal of Geomechanics},
+	year={2012},
+	publisher={American Society of Civil Engineers},
+	doi = {10.1061/(ASCE)GM.1943-5622.0000277}
+}
+
+@article{Epif2012a,
+	title={Proizvodstvo kuskovogo torfa, ekstrudirovanie, forma zakhodnoi i kalibriruyushchei chasti fil'ery matritsy, metod diskretnykh elementov [RUS]},
+	author={Epifantsev, K. and Mikhailov, A. and Gladky, A.},
+	journal={Mining informational and analytical bulletin (scientific and technical journal)},
+	year={2012},
+	publisher={The joint-stock company Gornaya Kniga},
+	number = {3},
+	pages = {212-219},
+	issn = {0236-1493},
+}
+
+
+@article {Duriez2013,
+	author = {Duriez, Jérôme and Darve, Félix and Donzé, Frédéric-Victor},
+	title = {Incrementally non-linear plasticity applied to rock joint modelling},
+	journal = {International Journal for Numerical and Analytical Methods in Geomechanics},
+	volume = {37},
+	number = {5},
+	url = {http://dx.doi.org/10.1002/nag.1105},
+	doi = {10.1002/nag.1105},
+	pages = {453--477},
+	year = {2013}
+}
+
+@article{Nicot2013,
+	title = {On the definition of the stress tensor in granular media},
+	journal = {International Journal of Solids and Structures},
+	year = {2013},
+	doi = {10.1016/j.ijsolstr.2013.04.001},
+	url = {http://www.sciencedirect.com/science/article/pii/S0020768313001492},
+	author = {François Nicot and Nejib Hadda and Mohamed Guessasma and Jerome Fortin and Olivier Millet}
+}
+

=== modified file 'doc/yade-conferences.bib'
--- doc/yade-conferences.bib	2012-09-08 01:19:45 +0000
+++ doc/yade-conferences.bib	2013-03-05 10:48:14 +0000
@@ -452,3 +452,56 @@
 	doi = {10.1039/9781849735032-00187},
 	url = {http://pubs.rsc.org/en/content/chapter/bk9781849733601-00187/978-1-84973-503-2}
 }
+
+@incollection{Chareyre2012b,
+	title = {The properties of some stress tensors investigated by DEM simulations},
+	author = {B. Chareyre and L. Scholtès and F. Darve},
+	month = {Aug},
+	year = {2012},
+	booktitle = {Euromech Colloquium 539; Mechanics of Unsaturated Porous Media: Effective Stress principle; from micromechanics to thermodynamics},
+	address = {Utrecht, Netherlands},
+	url = {http://www.geo.uu.nl/hydrogeology/Colloquium2012/Bruno%20Chareyre_Euromech.pdf}
+}
+
+@incollection{Chareyre2012c,
+	title = {Micro-poromechanics: recent advances in numerical models and perspectives},
+	author = {B. Chareyre},
+	booktitle = {ICACM symposium 2012, The role of structure on emerging material properties},
+	year = {2012},
+	month = {June},
+	address = {New York, USA}
+}
+
+@incollection{Michallet2012,
+	title = {Physical and numerical modelling of sand liquefaction in waves interacting with a vertical wall},
+	author = {H. Michallet and E. Catalano and C. Berni and V. Rameliarison and E. Barthélémy},
+	month = {Aug},
+	year = {2012},
+	booktitle = {ICSE6 - 6th International conference on Scour and Erosion},
+	address = {Paris, France}
+}
+
+@incollection{Hasan2010b,
+	title = {Microtomography-based Discrete Element Modeling to Simulate Snow Microstructure Deformation},
+	author = {A. Hasan and B. Chareyre and J. Kozicki and F. Flin and F. Darve and J. Meyssonnier},
+	booktitle = {AGU Fall Meeting Abstracts},
+	volume = {1},
+	pages = {0566},
+	year = {2010}
+}
+
+@incollection{Tran2012b,
+	title={Coupling of Random Field Theory and the Discrete Element Method in the Reliability Analysis of Geotechnical Problems},
+	author={Tran, V.D.H and Meguid, M.A and Chouinard, L.E},
+	booktitle={Canadian Society for Civil Engineering (CSCE) Annual Conference 2012, Edmonton},
+	year={2012},
+	month={May}
+}
+
+@incollection{Tran2012b,
+	title={A Discrete Element Study of the Earth Pressure Distribution on Cylindrical Shafts},
+	author={Tran, V.D.H and Meguid, M.A and Chouinard, L.E},
+	booktitle={Tunnelling Association of Canada (TAC) Conference 2012, Montreal},
+	year={2012},
+	month={October}
+}

=== modified file 'doc/yade-theses.bib'
--- doc/yade-theses.bib	2012-09-08 01:19:45 +0000
+++ doc/yade-theses.bib	2012-12-11 21:53:45 +0000
@@ -87,7 +87,8 @@
 	author={Chen, J.},
 	school = {University of Tennessee, Knoxville},
 	journal={Doctoral Dissertations},
-	year={2011}
+	year={2011},
+	url = {http://trace.tennessee.edu/cgi/viewcontent.cgi?article=2102&context=utk_graddiss}
 }
 
 @article{Favier2009c,

=== modified file 'examples/CapillaryPhys-example.py'
--- examples/CapillaryPhys-example.py	2012-03-12 20:00:24 +0000
+++ examples/CapillaryPhys-example.py	2013-03-28 10:53:06 +0000
@@ -30,7 +30,7 @@
 #generate particles:
 sp=pack.SpherePack()
 sp.makeCloud(lowercorner,uppercorner,.0002,rRelFuzz=.3)
-O.bodies.append([utils.sphere(c,r,material=SphereMat) for c,r in sp])
+O.bodies.append([sphere(c,r,material=SphereMat) for c,r in sp])
 
 #generate boundary:
 O.bodies.append(geom.facetBox(uppercorner/2,uppercorner/2,wire=True,fixed=True,material=SphereMat))
@@ -65,7 +65,7 @@
 	]
 
 #set time step and run simulation:
-O.dt=0.5*utils.PWaveTimeStep()
+O.dt=0.5*PWaveTimeStep()
 
 from yade import qt
 qt.View()

=== modified file 'examples/ResetRandomPosition.py'
--- examples/ResetRandomPosition.py	2012-10-05 14:33:55 +0000
+++ examples/ResetRandomPosition.py	2013-03-28 10:53:06 +0000
@@ -1,6 +1,6 @@
 # -*- coding: utf-8
 
-from yade import utils,pack,export,qt
+from yade import pack,export,qt
 import gts,os
 
 def Plane(v1,v2,v3,v4):
@@ -13,8 +13,8 @@
 es=0.3  # tangential restitution coefficient
 frictionAngle=radians(35)# 
 density=2700
-kw=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+kw=getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 # facets material
 facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) 
 # default spheres material
@@ -36,7 +36,7 @@
 # Create spheres
 sp=pack.SpherePack(); 
 sp.makeCloud(Vector3(-.5, -.5, 0),Vector3(.5, .5, .2), Rs, Rf, int(nSpheres), False)
-spheres=O.bodies.append([utils.sphere(s[0],s[1],color=(0.929,0.412,0.412),material=dfltSpheresMat) for s in sp])
+spheres=O.bodies.append([sphere(s[0],s[1],color=(0.929,0.412,0.412),material=dfltSpheresMat) for s in sp])
 
 # Create engines
 O.engines=[

=== modified file 'examples/baraban/baraban.py'
--- examples/baraban/baraban.py	2012-02-16 16:11:06 +0000
+++ examples/baraban/baraban.py	2013-03-28 10:55:47 +0000
@@ -10,7 +10,7 @@
 es = 0.3
 
 ## Import wall's geometry
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) # **params sets kn, cn, ks, cs
 sphereMat=O.materials.append(ViscElMat(density=Density,frictionAngle=frictionAngle,**params))
 from yade import ymport
@@ -25,7 +25,7 @@
             x = (i*2 - nbSpheres[0])*sphereRadius*1.1
             y = (j*2 - nbSpheres[1])*sphereRadius*1.1
             z = (k*2 - nbSpheres[2])*sphereRadius*1.1
-            s=utils.sphere([x,y,z],sphereRadius,material=sphereMat)
+            s=sphere([x,y,z],sphereRadius,material=sphereMat)
             O.bodies.append(s)
 
 ## Timestep 

=== modified file 'examples/baraban/rotating-cylinder.py'
--- examples/baraban/rotating-cylinder.py	2012-06-28 19:34:29 +0000
+++ examples/baraban/rotating-cylinder.py	2013-03-28 10:55:47 +0000
@@ -35,7 +35,7 @@
 print 'Generating cloud…'
 sp.makeCloud((-wd/2,-wd/2,-.5*cylHt),(wd/2,wd/2,.5*cylHt),rMean,0,int(nSpheres),False)
 sp.rotate((1,0,0),-pi/4)
-O.bodies.append([utils.sphere(s[0],s[1]) for s in sp])
+O.bodies.append([sphere(s[0],s[1]) for s in sp])
 
 O.engines=[
 	ForceResetter(),
@@ -48,7 +48,7 @@
 	RotationEngine(rotateAroundZero=True,zeroPoint=(0,0,0),rotationAxis=(0,1,1),angularVelocity=30*(2*pi/60),ids=cylIds,label='rotor'),
 	NewtonIntegrator(damping=.3,gravity=(0,0,-1e3)), # gravity artificially high, to make it faster going ;-)
 ]
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.stopAtIter=int(2*pi/(rotor.angularVelocity*O.dt))
 O.timingEnabled=True; timing.reset()
 

=== modified file 'examples/bulldozer/README'
--- examples/bulldozer/README	2010-05-02 20:53:04 +0000
+++ examples/bulldozer/README	2013-04-24 19:49:00 +0000
@@ -1,6 +1,6 @@
 bulldozer.py and bulldozerVTK.py show how simple it is possible to simulate relatively difficult things.
 
-bulldozer.py is using Law2_Dem3DofGeom_FrictPhys_Basic constitutive law for interaction between elements.
+bulldozer.py is using Law2_ScGeom_FrictPhys_CundallStrack constitutive law for interaction between elements.
 It stores screenshots from simulation in /tmp/bulldozer-????.png files and creates video then.
 
 bulldozerVTK.py is using Law2_ScGeom_ViscElPhys_Basic - visco-elastic model for interaction between elements.

=== modified file 'examples/bulldozer/bulldozer.py'
--- examples/bulldozer/bulldozer.py	2012-02-16 16:11:06 +0000
+++ examples/bulldozer/bulldozer.py	2013-04-24 19:49:00 +0000
@@ -1,7 +1,6 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 ### Simpificated buldozer simulation
-from yade import utils
 from numpy import linspace
 from numpy import arange
 import gts
@@ -60,14 +59,14 @@
 
 from yade import qt
 
-O.dt=2*utils.PWaveTimeStep() # We do not need now a high accuracy
+O.dt=2*PWaveTimeStep() # We do not need now a high accuracy
 O.engines=[
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb(),]),
 	InteractionLoop(
-		[Ig2_Sphere_Sphere_L3Geom(),Ig2_Facet_Sphere_L3Geom()],
+		[Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom()],
 		[Ip2_FrictMat_FrictMat_FrictPhys()],
-		[Law2_L3Geom_FrictPhys_ElPerfPl()],
+		[Law2_ScGeom_FrictPhys_CundallStrack()],
 	),
 	TranslationEngine(translationAxis=[1,0,0],velocity=5,ids=KnifeIDs), # Buldozer motion
 	NewtonIntegrator(damping=.3,gravity=(0,0,-9.8)),
@@ -81,4 +80,4 @@
 r.lightPos=Vector3(0,0,50)
 O.stopAtIter=2000
 O.run()
-#utils.encodeVideoFromFrames(snapshooter.savedSnapshots,out='/tmp/bulldozer.ogg',fps=2)
+#encodeVideoFromFrames(snapshooter.savedSnapshots,out='/tmp/bulldozer.ogg',fps=2)

=== modified file 'examples/bulldozer/bulldozerVTK.py'
--- examples/bulldozer/bulldozerVTK.py	2012-02-16 16:11:06 +0000
+++ examples/bulldozer/bulldozerVTK.py	2013-03-28 10:58:04 +0000
@@ -2,7 +2,6 @@
 # -*- coding: utf-8 -*-
 ### Simpificated buldozer simulation with VTK recorder
 ### vtk-files are saved in /tmp directory with names buldozer-*.vtk
-from yade import utils
 from numpy import linspace
 from numpy import arange
 import gts
@@ -28,7 +27,7 @@
 es = 0.3
 
 ## Materials
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) # **params sets kn, cn, ks, cs
 sphereMat=O.materials.append(ViscElMat(density=Density,frictionAngle=frictionAngle,**params))
 

=== modified file 'examples/chained-cylinders/CohesiveCylinderSphere.py'
--- examples/chained-cylinders/CohesiveCylinderSphere.py	2012-08-23 12:04:26 +0000
+++ examples/chained-cylinders/CohesiveCylinderSphere.py	2013-03-28 16:15:54 +0000
@@ -1,7 +1,6 @@
 # encoding: utf-8
-from yade import utils,pack,geom,qt
+from yade import pack,geom,qt
 from pylab import *
-import math
 qt.View()
 
 O.dt=5e-07
@@ -16,12 +15,12 @@
 
 cylindersBodies=[]
 for i in arange(0,0.3,0.3/15.):
-	cylindersBodies.append(utils.chainedCylinder(begin=Vector3(i,0,0),radius=rCyl,end=Vector3(i+0.3/15.,0,0),fixed=False,wire=False,material='cylindermat'))
+	cylindersBodies.append(chainedCylinder(begin=Vector3(i,0,0),radius=rCyl,end=Vector3(i+0.3/15.,0,0),fixed=False,wire=False,material='cylindermat'))
 ChainedState.currentChain=ChainedState.currentChain+1
 O.bodies[0].state.blockedDOFs='xyzXYZ'
 O.bodies[-1].state.blockedDOFs='xyzXYZ'
 
-O.bodies.append(utils.sphere([0.15,0,2.*rCyl],rCyl,wire=False,fixed=False,material='spheremat'))
+O.bodies.append(sphere([0.15,0,2.*rCyl],rCyl,wire=False,fixed=False,material='spheremat'))
 
 def main():
 	global Fn,Ft

=== modified file 'examples/chained-cylinders/chained-cylinder-roots.py'
--- examples/chained-cylinders/chained-cylinder-roots.py	2012-08-23 12:04:26 +0000
+++ examples/chained-cylinders/chained-cylinder-roots.py	2013-03-28 16:15:54 +0000
@@ -4,8 +4,7 @@
 
 # Experiment beam-like behaviour with chained cylinders + CohFrict connexions
 
-from yade import utils,pack
-import math
+from yade import pack
 
 young=4.0e6
 poisson=3
@@ -32,8 +31,8 @@
  	Ns=sp.makeCloud(Vector3(-0.3,0.2,-1.0),Vector3(+0.3,+0.5,+1.0),-1,.2,Ns,False,0.8)
 	sp.save("cloud4cylinders"+`Ns`)
 
-O.bodies.append([utils.sphere(center,rad,material='spheremat') for center,rad in sp])
-walls=utils.aabbWalls((Vector3(-0.3,-0.15,-1),Vector3(+0.3,+1.0,+1)),thickness=.1,material='walllmat')
+O.bodies.append([sphere(center,rad,material='spheremat') for center,rad in sp])
+walls=aabbWalls((Vector3(-0.3,-0.15,-1),Vector3(+0.3,+1.0,+1)),thickness=.1,material='walllmat')
 wallIds=O.bodies.append(walls)
 
 O.initializers=[
@@ -71,10 +70,10 @@
 		omega=20/float(Ne); hy=0.0; hz=0.05; hx=1.5;
 		px=float(i)*hx/float(Ne)-0.8+dxj; py=sin(float(i)*omega)*hy+dyj; pz=cos(float(i)*omega)*hz+dzj;
 		px2=float(i+1.)*hx/float(Ne)-0.8+dxj; py2=sin(float(i+1.)*omega)*hy+dyj; pz2=cos(float(i+1.)*omega)*hz+dzj;
-		utils.chainedCylinder(begin=Vector3(pz,py,px), radius=0.02,end=Vector3(pz2,py2,px2),color=Vector3(0.6,0.5,0.5),material='cylindermat')
+		chainedCylinder(begin=Vector3(pz,py,px), radius=0.02,end=Vector3(pz2,py2,px2),color=Vector3(0.6,0.5,0.5),material='cylindermat')
 		if (i == Ne-1): #close the chain with a node of size 0
 			print "closing chain"
-			b=utils.chainedCylinder(begin=Vector3(pz2,py2,px2), radius=0.02,end=Vector3(pz2,py2,px2),color=Vector3(0.6,0.5,0.5),material='cylindermat')
+			b=chainedCylinder(begin=Vector3(pz2,py2,px2), radius=0.02,end=Vector3(pz2,py2,px2),color=Vector3(0.6,0.5,0.5),material='cylindermat')
 			b.state.blockedDOFs='xyzXYZ'
 	ChainedState.currentChain=ChainedState.currentChain+1
 

=== modified file 'examples/chained-cylinders/chained-cylinder-spring.py'
--- examples/chained-cylinders/chained-cylinder-spring.py	2012-08-23 12:04:26 +0000
+++ examples/chained-cylinders/chained-cylinder-spring.py	2013-03-28 16:15:54 +0000
@@ -4,7 +4,6 @@
 
 # Experiment beam-like behaviour with chained cylinders + CohFrict connexions
 
-from yade import utils
 young=1.0e6
 poisson=4
 density=2.60e3 
@@ -35,7 +34,7 @@
 	omega=60.0/float(Ne); hy=0.10; hz=0.15;
 	px=float(i)*(omega/60.0); py=sin(float(i)*omega)*hy; pz=cos(float(i)*omega)*hz;
 	px2=float(i+1.)*(omega/60.0); py2=sin(float(i+1.)*omega)*hy; pz2=cos(float(i+1.)*omega)*hz;
-	utils.chainedCylinder(begin=Vector3(pz,py,px), radius=0.005,end=Vector3(pz2,py2,px2),color=Vector3(0.6,0.5,0.5))
+	chainedCylinder(begin=Vector3(pz,py,px), radius=0.005,end=Vector3(pz2,py2,px2),color=Vector3(0.6,0.5,0.5))
 
 def outp(id=1):
 	for i in O.interactions:
@@ -48,8 +47,7 @@
 yade.qt.View();
 
 
- #plot some results
-from math import *
+#plot some results
 from yade import plot
 plot.plots={'t':('pos1',None,'vel1')}
 def history():

=== added file 'examples/clumps/adaptClumpMasses-example.py'
--- examples/clumps/adaptClumpMasses-example.py	1970-01-01 00:00:00 +0000
+++ examples/clumps/adaptClumpMasses-example.py	2013-04-17 07:39:24 +0000
@@ -0,0 +1,54 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+'''This example shows usage of adaptClumpMasses().'''
+
+#define material for all bodies:
+id_Mat=O.materials.append(FrictMat(young=1e7,poisson=0.3,density=1000,frictionAngle=1))
+Mat=O.materials[id_Mat]
+
+#define engines:
+O.engines=[
+	ForceResetter(),
+	InsertionSortCollider([Bo1_Sphere_Aabb()]),
+	InteractionLoop(
+		[Ig2_Sphere_Sphere_ScGeom()],
+		[Ip2_FrictMat_FrictMat_FrictPhys()],
+		[Law2_ScGeom_FrictPhys_CundallStrack()]
+	),
+	NewtonIntegrator(damping=0.7,gravity=[0,0,-10])
+]
+
+#append spheres:
+sphereList = []
+sphereList.append(O.bodies.append(sphere((0,0,0),radius=.5,material=Mat)))
+sphereList.append(O.bodies.append(sphere((.5,0,0),radius=.25,material=Mat)))
+sphereList.append(O.bodies.append(sphere((0,.3,0),radius=.5,material=Mat)))
+sphereList.append(O.bodies.append(sphere((0,0,.3),radius=.5,material=Mat)))
+
+#clump spheres:
+idClump=O.bodies.clump(sphereList)
+
+from yade import qt
+qt.Controller()
+qt.View()
+
+def printClumpMasses():
+	for b in O.bodies:
+		if b.isClump:
+			print 'Clump ',b.id,' with mass ',b.state.mass,' has following members:'
+			keys = b.shape.members.keys()
+			for ii in range(0,len(keys)):
+				print '- Body ',keys[ii],' with mass ',O.bodies[keys[ii]].state.mass
+
+print 'Mass info BEFORE adaptClumpMasses() is called: ----------------'
+printClumpMasses()
+
+massInfo = O.bodies.adaptClumpMasses([],10000000)		#give an empty list [] if no body should be excluded, number of grid points is set to 10000000
+
+#NOTE: the higher the number of grid points, the more precisely is the result, 
+#      but high numbers of clumps + high number of grid points = a looooong coffee break ...
+
+print 'Mass info AFTER adaptClumpMasses() is called: -----------------'
+printClumpMasses()
+print 'output of adaptClumpMasses(): ',massInfo

=== added file 'examples/clumps/addToClump-example.py'
--- examples/clumps/addToClump-example.py	1970-01-01 00:00:00 +0000
+++ examples/clumps/addToClump-example.py	2013-03-28 11:01:40 +0000
@@ -0,0 +1,81 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+'''This example shows usage of addToClump() and appendClumped().'''
+
+#define material for all bodies:
+id_Mat=O.materials.append(FrictMat(young=1e6,poisson=0.3,density=1000,frictionAngle=1))
+Mat=O.materials[id_Mat]
+
+#define engines:
+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()]
+	),
+	NewtonIntegrator(damping=0.7,gravity=[0,0,-10])
+]
+
+#create a box:
+id_box = O.bodies.append(box((0,0,0),(2,2,.1),fixed=True,material=Mat))
+
+
+#### show how to use appendClumped():
+
+
+#create 2 clumps:
+clump1=O.bodies.appendClumped([\
+sphere([0,0,1], material=Mat, radius=0.5),\
+sphere([0.2,0,1], material=Mat, radius=0.5)\
+])
+clump2=O.bodies.appendClumped([\
+sphere([3,1,2], material=Mat, radius=0.5),\
+sphere([3.2,1,2], material=Mat, radius=0.5)\
+])
+
+#get clump ids:
+id_clump1 = clump1[0]
+id_clump2 = clump2[0]
+
+#definition for getting informations from all clumps:
+def getClumpInfo():
+	for b in O.bodies:
+		if b.isClump:
+			print 'Clump ',b.id,' has following members:'
+			keys = b.shape.members.keys()
+			for ii in range(0,len(keys)):
+				print '- Body ',keys[ii]
+
+
+#### show how to use addToClump():
+
+
+#create a new sphere:
+id_new=O.bodies.append(sphere([0,0.2,1], material=Mat, radius=0.5))
+
+print '\nSTATE before adding sphere to clump ------------'
+getClumpInfo()
+
+#add a sphere to the clump:
+O.bodies.addToClump(id_new,id_clump1)
+
+print '\nSTATE after adding sphere to clump ------------'
+getClumpInfo()
+
+#add a clump to a clump:
+O.bodies.addToClump(id_clump2,id_clump1)
+
+print '\nSTATE after adding the second clump to clump ------------'
+getClumpInfo()
+
+#try to add clump member to a clump (should give error message):
+#O.bodies.addToClump(1,id_clump1)
+#try to add clump to the same clump (should give error message):
+#O.bodies.addToClump(id_clump1,id_clump1)
+
+O.dt=1e-6
+
+print '\nPress Play button ... '

=== modified file 'examples/clumps/clump-hopper-viscoelastic.py'
--- examples/clumps/clump-hopper-viscoelastic.py	2012-04-13 16:27:00 +0000
+++ examples/clumps/clump-hopper-viscoelastic.py	2013-03-28 11:01:40 +0000
@@ -1,6 +1,6 @@
 # -*- coding: utf-8
 
-from yade import utils,pack,export,qt
+from yade import pack,export,qt
 import gts,os,random,itertools
 from numpy import *
 
@@ -11,7 +11,7 @@
 frictionAngle=radians(35)# 
 density=2700
 # facets material
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) # **params sets kn, cn, ks, cs
 # default spheres material
 dfltSpheresMat=O.materials.append(ViscElMat(density=density,frictionAngle=frictionAngle, **params)) 
@@ -46,12 +46,12 @@
 # Create clumps...
 clumpColor=(0.0, 0.5, 0.5)
 for k,l in itertools.product(arange(0,10),arange(0,10)):
-	clpId,sphId=O.bodies.appendClumped([utils.sphere(Vector3(x0t+Rs*(k*4+2),y0t+Rs*(l*4+2),i*Rs*2+zt),Rs,color=clumpColor,material=dfltSpheresMat) for i in xrange(4)])
+	clpId,sphId=O.bodies.appendClumped([sphere(Vector3(x0t+Rs*(k*4+2),y0t+Rs*(l*4+2),i*Rs*2+zt),Rs,color=clumpColor,material=dfltSpheresMat) for i in xrange(4)])
 
 # ... and spheres
 spheresColor=(0.4, 0.4, 0.4)
 for k,l in itertools.product(arange(0,9),arange(0,9)):
-	sphAloneId=O.bodies.append( [utils.sphere( Vector3(x0t+Rs*(k*4+4),y0t+Rs*(l*4+4),i*Rs*2.3+zt),Rs,color=spheresColor,material=dfltSpheresMat) for i in xrange(4) ] )
+	sphAloneId=O.bodies.append( [sphere( Vector3(x0t+Rs*(k*4+4),y0t+Rs*(l*4+4),i*Rs*2.3+zt),Rs,color=spheresColor,material=dfltSpheresMat) for i in xrange(4) ] )
 
 # Create engines
 O.engines=[

=== modified file 'examples/clumps/clump-inbox-viscoelastic.py'
--- examples/clumps/clump-inbox-viscoelastic.py	2012-04-13 16:27:00 +0000
+++ examples/clumps/clump-inbox-viscoelastic.py	2013-03-28 11:01:40 +0000
@@ -1,6 +1,6 @@
 # -*- coding: utf-8
 
-from yade import utils,pack,export,qt,geom
+from yade import pack,export,qt,geom
 import gts,os,random,itertools
 from numpy import *
 
@@ -11,7 +11,7 @@
 frictionAngle=radians(35)# 
 density=2700
 # facets material
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) # **params sets kn, cn, ks, cs
 # default spheres material
 dfltSpheresMat=O.materials.append(ViscElMat(density=density,frictionAngle=frictionAngle,**params)) 
@@ -25,11 +25,11 @@
 
 # Create clumps...
 for j in xrange(10):
-	clpId,sphId=O.bodies.appendClumped([utils.sphere(Vector3(0,Rs*2*i,(j+1)*Rs*2),Rs,material=dfltSpheresMat) for i in xrange(4)])
+	clpId,sphId=O.bodies.appendClumped([sphere(Vector3(0,Rs*2*i,(j+1)*Rs*2),Rs,material=dfltSpheresMat) for i in xrange(4)])
 	
 
 # ... and spheres
-sphAloneId=O.bodies.append( [utils.sphere( Vector3(0.5,Rs*2*i,(j+1)*Rs*2), Rs, material=dfltSpheresMat) for i in xrange(4) ] )
+sphAloneId=O.bodies.append( [sphere( Vector3(0.5,Rs*2*i,(j+1)*Rs*2), Rs, material=dfltSpheresMat) for i in xrange(4) ] )
 
 # Create engines
 O.engines=[

=== modified file 'examples/clumps/clump-viscoelastic.py'
--- examples/clumps/clump-viscoelastic.py	2012-04-18 19:15:45 +0000
+++ examples/clumps/clump-viscoelastic.py	2013-03-28 11:01:40 +0000
@@ -1,6 +1,6 @@
 # -*- coding: utf-8
 
-from yade import utils,pack,export,qt
+from yade import pack,export,qt
 import gts,os,random,itertools
 from numpy import *
 
@@ -12,7 +12,7 @@
 frictionAngle=radians(35)# 
 density=2700
 # facets material
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) # **params sets kn, cn, ks, cs
 # default spheres material
 dfltSpheresMat=O.materials.append(ViscElMat(density=density,frictionAngle=frictionAngle,**params)) 
@@ -29,7 +29,7 @@
 plnIds1=O.bodies.append(pack.gtsSurface2Facets(plnSurf1,material=facetMat,color=(0,1,0)))
 
 # Create clumps
-clpId,sphId=O.bodies.appendClumped([utils.sphere(Vector3(0,Rs*2*i,Rs*2),Rs,material=dfltSpheresMat) for i in xrange(4)])
+clpId,sphId=O.bodies.appendClumped([sphere(Vector3(0,Rs*2*i,Rs*2),Rs,material=dfltSpheresMat) for i in xrange(4)])
 
 # Create engines
 O.engines=[

=== added file 'examples/clumps/releaseFromClump-example.py'
--- examples/clumps/releaseFromClump-example.py	1970-01-01 00:00:00 +0000
+++ examples/clumps/releaseFromClump-example.py	2013-03-28 11:01:40 +0000
@@ -0,0 +1,76 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+'''This example shows usage of releaseFromClump() and clump().'''
+
+#define material for all bodies:
+id_Mat=O.materials.append(FrictMat(young=1e6,poisson=0.3,density=1000,frictionAngle=1))
+Mat=O.materials[id_Mat]
+
+#define engines:
+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()]
+	),
+	NewtonIntegrator(damping=0.7,gravity=[0,0,-10])
+]
+
+#create a box:
+id_box = O.bodies.append(box((0,0,0),(5,5,.1),fixed=True,material=Mat))
+
+
+#### show how to use clump():
+
+
+#create spheres parallel to x-axis:
+bodyList1 = []
+for ii in range(-2,2):
+	bodyList1.append(O.bodies.append(sphere((ii,0,1),radius=.5,material=Mat)))
+
+#create spheres parallel to y-axis:
+bodyList2 = []
+for ii in range(-3,2):
+	bodyList2.append(O.bodies.append(sphere((-1,ii,1.5),radius=.5,material=Mat)))
+
+#create 2 clumps, and give each clump a different color
+idClump1=O.bodies.clump(bodyList1)
+idClump2=O.bodies.clump(bodyList2)
+for ii in bodyList1:
+	O.bodies[ii].shape.color=(100,100,100)
+for ii in bodyList2:
+	O.bodies[ii].shape.color=(200,200,200)
+
+#definition for getting informations from all clumps:
+def getClumpInfo():
+	for b in O.bodies:
+		if b.isClump:
+			print 'Clump ',b.id,' has following members:'
+			keys = b.shape.members.keys()
+			for ii in range(0,len(keys)):
+				print '- Body ',keys[ii]
+
+O.dt=1e-6
+
+
+#### show how to use releaseFromClump():
+
+
+print '\nSTATE before releasing spheres from clump ------------'
+getClumpInfo()
+
+raw_input('\nPress Play button ... and look what happens.\n Then press Pause button and press ENTER on console!')
+
+for ii in bodyList2:
+	if ii > max(bodyList2)-2:
+		clId = O.bodies[ii].clumpId
+		O.bodies.releaseFromClump(ii,clId)
+		print 'Sphere ',ii,' released from clump ',clId
+
+print '\nSTATE after releasing spheres from clump ------------'
+getClumpInfo()
+
+print '\nPress Play button again ... '

=== added file 'examples/clumps/replaceByClumps-example.py'
--- examples/clumps/replaceByClumps-example.py	1970-01-01 00:00:00 +0000
+++ examples/clumps/replaceByClumps-example.py	2013-04-16 12:37:01 +0000
@@ -0,0 +1,90 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+'''This example shows usage of clumpTemplate(), replaceByClumps() and getRoundness().'''
+
+#define material for all bodies:
+id_Mat=O.materials.append(FrictMat(young=1e7,poisson=0.3,density=1000,frictionAngle=1))
+Mat=O.materials[id_Mat]
+
+#define engines:
+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()]
+	),
+	NewtonIntegrator(damping=0.7,gravity=[0,0,-10])
+]
+
+
+from yade import qt
+qt.Controller()
+qt.View()
+
+#create a box:
+id_box = O.bodies.append(box((0,0,0),(2,2,.1),fixed=True,material=Mat))
+
+#create assembly of spheres:
+sp=pack.SpherePack()
+sp.makeCloud(minCorner=(-1.5,-1.5,.1),maxCorner=(1.5,1.5,2),rMean=.2,rRelFuzz=.5,num=100,periodic=False)
+O.bodies.append([sphere(c,r,material=Mat) for c,r in sp])
+
+print len(sp),' particles generated.'
+print 'Roundness coefficient without clumps is: ',O.bodies.getRoundness([])			#give an empty list [] if no body should be excluded
+
+
+#### show how to use makeClumpTemplate():
+
+
+#dyad:
+relRadList1 = [1,1]
+relPosList1 = [[1,0,0],[-1,0,0]]
+
+#peanut:
+relRadList2 = [.5,1,.5]
+relPosList2 = [[1,0,0],[0,0,0],[-1,0,0]]
+
+#stick:
+relRadList3 = [1,1,1,1,1]
+relPosList3 = [[0,1,0],[0,2,0],[0,3,0],[0,4,0],[0,5,0]]
+
+templates= []
+templates.append(clumpTemplate(relRadii=relRadList1,relPositions=relPosList1))
+templates.append(clumpTemplate(relRadii=relRadList2,relPositions=relPosList2))
+templates.append(clumpTemplate(relRadii=relRadList3,relPositions=relPosList3))
+
+
+#### show how to use replaceByClumps():
+
+
+#replace by 50% dyads, 30% peanuts and 10% sticks:
+O.bodies.replaceByClumps(templates,[.5,.3,.1])
+
+
+#### show how to use getRoundness():
+
+
+#create a list of all standalone spheres:
+standaloneList = []
+for b in O.bodies:
+	if b.isStandalone:
+		standaloneList.append(b.id)
+
+print 'Roundness coefficient for spheres and clumps is: ',O.bodies.getRoundness([])			#give an empty list [] if no body should be excluded
+print 'Roundness coefficient just for clumps is: ',O.bodies.getRoundness(standaloneList)
+
+O.dt=1e-6
+
+#NOTE, that after replacing some overlaps may occur.
+#So after replacing calm() function may be helpful:
+if 0:
+	print '\nPlease wait a minute ...\n'
+	O.engines=O.engines+[PyRunner(iterPeriod=10000,command='calm()',label='calmRunner')]
+	O.run(1000000,True)
+	calmRunner.dead=True
+
+print '\nPress Play button ... '
+                

=== modified file 'examples/clumps/triax-basic-with-clumps.py'
--- examples/clumps/triax-basic-with-clumps.py	2012-09-21 11:40:55 +0000
+++ examples/clumps/triax-basic-with-clumps.py	2013-03-28 11:01:40 +0000
@@ -1,6 +1,6 @@
 # encoding: utf-8
 # Copyright (C) 2012 by Bruno Chareyre
-# An update of the original script for Janek Kozicki
+# An update of the original script from Janek Kozicki
 
 from yade import pack
 from numpy import arange
@@ -22,9 +22,14 @@
 	ids_spheres=O.bodies.appendClumped(pack.regularHexa(pack.inEllipsoid((mn[0]+xyz[0]*(mx[0]-mn[0])/d,mn[0]+xyz[1]*(mx[1]-mn[1])/d,mn[2]+xyz[2]*(mx[2]-mn[2])/d),(0.45+random.random()*0.1,0.45+random.random()*0.1,0.45+random.random()*0.1)),radius=0.15+random.random()*0.05,gap=0,color=[random.random(),random.random(),random.random()]))
 
 ## create walls around the packing
-walls=utils.aabbWalls(material='frictionless')
+walls=aabbWalls(material='frictionless')
 wallIds=O.bodies.append(walls)
 
+from yade import qt
+qt.Controller()
+qt.View()
+
+
 ## hope that we got the ids right?!
 triax=TriaxialCompressionEngine(
 	wall_bottom_id=wallIds[2],
@@ -64,8 +69,6 @@
 	NewtonIntegrator(damping=.4)
 ]
 
-O.dt=.5*utils.PWaveTimeStep() # initial timestep, to not explode right away
-
 #yade.plot.plots={'eps':('sigma',)}
 
 #O.saveTmp('initial');

=== modified file 'examples/concrete/README'
--- examples/concrete/README	2009-12-06 17:18:16 +0000
+++ examples/concrete/README	2013-04-24 19:49:00 +0000
@@ -10,4 +10,3 @@
 See comments at the beginning of uniax.py for more information.
 
 The periodic.py is uniax.py, but running on a periodic sample.
-It is only experimental at this moment.

=== removed file 'examples/concrete/cpm-dem3dof-scgeom.py'
--- examples/concrete/cpm-dem3dof-scgeom.py	2012-10-05 14:33:55 +0000
+++ examples/concrete/cpm-dem3dof-scgeom.py	1970-01-01 00:00:00 +0000
@@ -1,86 +0,0 @@
-from yade import plot
-
-# setup 2 interactions on 2 otherwise identical couples of spheres
-# one is handled by Law2_Dem3DofGeom_CpmPhys_Cpm and the other by Law2_ScGeom_CpmPhys_Cpm
-
-# move the second sphere tangentially or rotate it, pick [0] or [1]
-mode=['mov','rot'][1]
-# number of steps to do (some influence on the incremental computation)
-nSteps=100
-
-
-r1,r2=1e-3,1e-3
-dist=r1+r2
-offset=Vector3(0,0,2*dist)
-p1,p2=Vector3(0,0,0),Vector3(dist,0,0)
-O.materials.append(CpmMat(young=30e9,poisson=.2,frictionAngle=atan(.8),sigmaT=3e6,crackOpening=1e-6,epsCrackOnset=1e-4,neverDamage=False,plTau=-1,plRateExp=0,dmgTau=-1,dmgRateExp=0))#,G_over_E=.2
-# first 2 spheres used for Dem3DofGeom
-# the other 2 used for ScGeom (#3 is dynamic, since ScGeom needs that)
-O.bodies.append([utils.sphere(p1,r1,fixed=True),utils.sphere(p2,r2,fixed=True)])
-O.bodies.append([utils.sphere(p1+offset,r1,fixed=True),utils.sphere(p2+offset,r2,fixed=True)])
-
-
-O.engines=[IGeomDispatcher([Ig2_Sphere_Sphere_Dem3DofGeom()]),IPhysDispatcher([Ip2_CpmMat_CpmMat_CpmPhys()])]
-i1=utils.createInteraction(0,1) # caches functors, no need to specify them in the main loop
-O.engines=[IGeomDispatcher([Ig2_Sphere_Sphere_ScGeom()]),IPhysDispatcher([Ip2_CpmMat_CpmMat_CpmPhys()])]
-i2=utils.createInteraction(2,3)
-
-O.engines=[
-	ForceResetter(),
-	InteractionLoop([],[],[Law2_ScGeom_CpmPhys_Cpm(),Law2_Dem3DofGeom_CpmPhys_Cpm(yieldSurfType=0)]),
-	StepDisplacer(ids=[1,3],setVelocities=True,label='jumper'), # displace non-dynamic #1, set velocity on #3
-	NewtonIntegrator(damping=0),
-	PyRunner(iterPeriod=1,initRun=True,command='plotData()'),
-]
-
-def plotData():
-	allData={}
-	# gather same data for both configurations, suffix their labels with -DD/-Sc
-	for i,key,sphere in zip([i1,i2],['-DD','-Sc'],[1,3]):
-		data=dict(
-			zRot=O.bodies[sphere].state.ori.toAxisAngle()[1],
-			zShift=O.bodies[sphere].state.pos[2],
-			epsT=i.phys.epsT.norm() if key=='-Sc' else i.geom.strainT().norm(),
-			Ft=i.phys.shearForce.norm(),
-			epsN=i.phys.epsN,
-			#epsPlSum=i.phys.epsPlSum,
-			relResStr=i.phys.relResidualStrength,
-			dist=(O.bodies[i.id1].state.pos-O.bodies[i.id2].state.pos).norm(),
-			sigmaT=i.phys.sigmaT.norm()
-		)
-		for k in data: allData[k+key]=data[k]
-	plot.addData(allData)
-
-if mode=='mov':
-	jumper.mov=Vector3(0,0,1/(1e4*nSteps))
-elif mode=='rot':
-	jumper.rot=Quaternion(Vector3.UnitZ,1/(1e4*nSteps))
-
-O.run(nSteps,True)
-if mode=='mov':
-	plot.plots={'zShift-DD':(
-		#('epsT-DD','g-'),('epsT-Sc','r^'),
-		('dist-DD','g-'),('dist-Sc','r^'),
-		None,
-		('sigmaT-DD','b-'),('sigmaT-Sc','m^')
-		#('relResStr-DD','b-'),('relResStr-Sc','m^')
-		#('epsN-DD','b-'),('epsN-Sc','m^')
-	)}
-elif mode=='rot':
-	plot.plots={'zRot-DD':(
-		('epsT-DD','g|'),('epsT-Sc','r-'),
-		None,
-		('sigmaT-DD','b-'),('sigmaT-Sc','mv')
-	)}
-
-
-
-if 1:
-	f='/tmp/cpm-geom-'+mode+'.pdf'
-	plot.plot(noShow=True,subPlots=False).savefig(f)
-	print 'Plot saved to '+f
-	quit()
-else:
-	plot.plot(subPlots=False)
-
-

=== removed file 'examples/concrete/dem3dof-scgeom.table'
--- examples/concrete/dem3dof-scgeom.table	2010-07-22 13:52:50 +0000
+++ examples/concrete/dem3dof-scgeom.table	1970-01-01 00:00:00 +0000
@@ -1,21 +0,0 @@
-#
-# for use with uniax.py
-#
-# shows the (unexplained) influence of geometry implementation on macroscopic
-# tension-compression test. The tests are shown to be "objective" WRT Δt by
-# using different dtSafety values -- the difference is therefore not that the
-# incremental implementation is more sensitive to Δt.
-#
-# Computations with ScGeom as (variably) faster regarding computational t/step,
-# but are less efficient in multi-threading
-# (that might be due to the implementation of Law2_ScGeom_CpmPhys_Cpm, though)
-#
-# Run the batch using
-#
-# $ yade-trunk-multi --gnuplot=d3d-scg.gnuplot dem3dof-scgeom.table uniax.py
-#
-scGeom	dtSafety
-False	.8
-False .2
-True .8
-True .2

=== modified file 'examples/concrete/interaction-histogram.py'
--- examples/concrete/interaction-histogram.py	2010-07-22 13:52:50 +0000
+++ examples/concrete/interaction-histogram.py	2013-03-28 11:02:35 +0000
@@ -41,6 +41,6 @@
 
 # predefined function
 pylab.figure()
-utils.plotDirections(noShow=True).savefig('/tmp/a.pdf')
+plotDirections(noShow=True).savefig('/tmp/a.pdf')
 
 pylab.show()

=== modified file 'examples/concrete/periodic.py'
--- examples/concrete/periodic.py	2012-10-05 14:33:55 +0000
+++ examples/concrete/periodic.py	2013-04-24 19:49:00 +0000
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import division
 
-from yade import utils,plot,pack
+from yade import plot,pack
 import time, sys, os, copy
 
 """
@@ -33,7 +33,7 @@
 
 
 # default parameters or from table
-utils.readParamsFromTable(noTableOk=True, # unknownOk=True,
+readParamsFromTable(noTableOk=True, # unknownOk=True,
 	young=24e9,
 	poisson=.2,
 	sigmaT=3.5e6,
@@ -79,13 +79,13 @@
 
 import numpy
 avgRadius=numpy.average([r for c,r in sp])
-O.bodies.append([utils.sphere(c,r,color=utils.randomColor()) for c,r in sp])
+O.bodies.append([sphere(c,r,color=randomColor()) for c,r in sp])
 O.periodic=True
 O.cell.setBox(sp.cellSize)
 axis=2
 ax1=(axis+1)%3
 ax2=(axis+2)%3
-O.dt=dtSafety*utils.PWaveTimeStep()
+O.dt=dtSafety*PWaveTimeStep()
 
 import yade.plot as yp
 
@@ -93,16 +93,16 @@
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb(aabbEnlargeFactor=intRadius,label='is2aabb')],verletDist=.05*avgRadius),
 	InteractionLoop(
-		[Ig2_Sphere_Sphere_Dem3DofGeom(distFactor=intRadius,label='ss2d3dg')],
+		[Ig2_Sphere_Sphere_ScGeom(interactionDetectionFactor=intRadius,label='ss2d3dg')],
 		[Ip2_CpmMat_CpmMat_CpmPhys()],
-		[Law2_Dem3DofGeom_CpmPhys_Cpm()],
+		[Law2_ScGeom_CpmPhys_Cpm()],
 	),
 	NewtonIntegrator(damping=damping,label='newton'),
 	CpmStateUpdater(realPeriod=1,label='updater'),
 	#
 	#UniaxialStrainer(strainRate=strainRateTension,axis=axis,asymmetry=0,posIds=posIds,negIds=negIds,crossSectionArea=crossSectionArea,blockDisplacements=False,blockRotations=False,setSpeeds=setSpeeds,label='strainer'),
 	#
-	PeriTriaxController(goal=[1,1,1],stressMask=( (7^(1<<axis | 1<<ax1)) if biaxial else (7^(1<<axis)) ),label='strainer',useDem3Dof=False,globUpdate=2),
+	PeriTriaxController(goal=[1,1,1],stressMask=( (7^(1<<axis | 1<<ax1)) if biaxial else (7^(1<<axis)) ),label='strainer',globUpdate=2),
 	PyRunner(virtPeriod=1e-5/strainRateTension,command='addPlotData()',label='plotDataCollector'),
 	PyRunner(realPeriod=4,command='stopIfDamaged()',label='damageChecker'),
 ]
@@ -147,7 +147,7 @@
 	print "init done, will now run."
 	O.step(); O.step(); # to create initial contacts
 	# now reset the interaction radius and go ahead
-	ss2d3dg.distFactor=-1.
+	ss2d3dg.interactionDetectionFactor=-1.
 	is2aabb.aabbEnlargeFactor=-1.
 	O.run()
 
@@ -186,5 +186,5 @@
 	yade.plot.addData(t=O.time,i=O.iter,eps=strainer.strain[axis],eps_=strainer.strain[axis],sigma=strainer.stress[axis]+isoPrestress,eps1=strainer.strain[ax1],eps2=strainer.strain[ax2],sig1=strainer.stress[ax1],sig2=strainer.stress[ax2],relResid=updater.avgRelResidual)
 
 initTest()
-utils.waitIfBatch()
+waitIfBatch()
 

=== modified file 'examples/concrete/uniax.py'
--- examples/concrete/uniax.py	2012-10-05 14:33:55 +0000
+++ examples/concrete/uniax.py	2013-04-24 19:49:00 +0000
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 from __future__ import division
 
-from yade import utils,plot,pack,timing,eudoxos
+from yade import plot,pack,timing,eudoxos
 import time, sys, os, copy
 
 #import matplotlib
@@ -39,14 +39,14 @@
 
 
 # default parameters or from table
-utils.readParamsFromTable(noTableOk=True, # unknownOk=True,
+readParamsFromTable(noTableOk=True, # unknownOk=True,
 	young=24e9,
 	poisson=.2,
 
 	sigmaT=3.5e6,
 	frictionAngle=atan(0.8),
 	epsCrackOnset=1e-4,
-	crackOpening=1e-6,
+	relDuctility=30,
 
 	intRadius=1.5,
 	dtSafety=.8,
@@ -62,9 +62,6 @@
 
 	# isotropic confinement (should be negative)
 	isoPrestress=0,
-
-	# use the ScGeom variant
-	scGeom=False
 )
 
 from yade.params.table import *
@@ -75,30 +72,30 @@
 # make geom; the dimensions are hard-coded here; could be in param table if desired
 # z-oriented hyperboloid, length 20cm, diameter 10cm, skirt 8cm
 # using spheres 7mm of diameter
-concreteId=O.materials.append(CpmMat(young=young,frictionAngle=frictionAngle,poisson=poisson,density=4800,sigmaT=sigmaT,crackOpening=crackOpening,epsCrackOnset=epsCrackOnset,isoPrestress=isoPrestress))
+concreteId=O.materials.append(CpmMat(young=young,frictionAngle=frictionAngle,poisson=poisson,density=4800,sigmaT=sigmaT,relDuctility=relDuctility,epsCrackOnset=epsCrackOnset,isoPrestress=isoPrestress))
 
 spheres=pack.randomDensePack(pack.inHyperboloid((0,0,-.5*specimenLength),(0,0,.5*specimenLength),.25*specimenLength,.17*specimenLength),spheresInCell=2000,radius=sphereRadius,memoizeDb='/tmp/triaxPackCache.sqlite',material=concreteId)
 #spheres=pack.randomDensePack(pack.inAlignedBox((-.25*specimenLength,-.25*specimenLength,-.5*specimenLength),(.25*specimenLength,.25*specimenLength,.5*specimenLength)),spheresInCell=2000,radius=sphereRadius,memoizeDb='/tmp/triaxPackCache.sqlite')
 O.bodies.append(spheres)
-bb=utils.uniaxialTestFeatures()
+bb=uniaxialTestFeatures()
 negIds,posIds,axis,crossSectionArea=bb['negIds'],bb['posIds'],bb['axis'],bb['area']
-O.dt=dtSafety*utils.PWaveTimeStep()
+O.dt=dtSafety*PWaveTimeStep()
 print 'Timestep',O.dt
 
-mm,mx=[pt[axis] for pt in utils.aabbExtrema()]
+mm,mx=[pt[axis] for pt in aabbExtrema()]
 coord_25,coord_50,coord_75=mm+.25*(mx-mm),mm+.5*(mx-mm),mm+.75*(mx-mm)
-area_25,area_50,area_75=utils.approxSectionArea(coord_25,axis),utils.approxSectionArea(coord_50,axis),utils.approxSectionArea(coord_75,axis)
+area_25,area_50,area_75=approxSectionArea(coord_25,axis),approxSectionArea(coord_50,axis),approxSectionArea(coord_75,axis)
 
 O.engines=[
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb(aabbEnlargeFactor=intRadius,label='is2aabb'),],verletDist=.05*sphereRadius),
 	InteractionLoop(
-		[Ig2_Sphere_Sphere_Dem3DofGeom(distFactor=intRadius,label='ss2d3dg') if not scGeom else Ig2_Sphere_Sphere_ScGeom(interactionDetectionFactor=intRadius,label='ss2sc')],
+		[Ig2_Sphere_Sphere_ScGeom(interactionDetectionFactor=intRadius,label='ss2sc')],
 		[Ip2_CpmMat_CpmMat_CpmPhys()],
-		[Law2_Dem3DofGeom_CpmPhys_Cpm(epsSoft=0) if not scGeom else Law2_ScGeom_CpmPhys_Cpm()],
+		[Law2_ScGeom_CpmPhys_Cpm()],
 	),
 	NewtonIntegrator(damping=damping,label='damper'),
-	CpmStateUpdater(realPeriod=1),
+	CpmStateUpdater(realPeriod=.5),
 	UniaxialStrainer(strainRate=strainRateTension,axis=axis,asymmetry=0,posIds=posIds,negIds=negIds,crossSectionArea=crossSectionArea,blockDisplacements=False,blockRotations=False,setSpeeds=setSpeeds,label='strainer'),
 	PyRunner(virtPeriod=1e-6/strainRateTension,realPeriod=1,command='addPlotData()',label='plotDataCollector',initRun=True),
 	PyRunner(realPeriod=4,command='stopIfDamaged()',label='damageChecker'),
@@ -132,8 +129,7 @@
 	print "init done, will now run."
 	O.step(); # to create initial contacts
 	# now reset the interaction radius and go ahead
-	if not scGeom: ss2d3dg.distFactor=-1.
-	else: ss2sc.interactionDetectionFactor=1.
+	ss2sc.interactionDetectionFactor=1.
 	is2aabb.aabbEnlargeFactor=-1.
 
 	O.run()
@@ -172,12 +168,12 @@
 		
 def addPlotData():
 	yade.plot.addData({'t':O.time,'i':O.iter,'eps':strainer.strain,'sigma':strainer.avgStress+isoPrestress,
-		'sigma.25':utils.forcesOnCoordPlane(coord_25,axis)[axis]/area_25+isoPrestress,
-		'sigma.50':utils.forcesOnCoordPlane(coord_50,axis)[axis]/area_50+isoPrestress,
-		'sigma.75':utils.forcesOnCoordPlane(coord_75,axis)[axis]/area_75+isoPrestress,
+		'sigma.25':forcesOnCoordPlane(coord_25,axis)[axis]/area_25+isoPrestress,
+		'sigma.50':forcesOnCoordPlane(coord_50,axis)[axis]/area_50+isoPrestress,
+		'sigma.75':forcesOnCoordPlane(coord_75,axis)[axis]/area_75+isoPrestress,
 		})
 plot.plot(subPlots=False)
 #O.run()
 initTest()
-utils.waitIfBatch()
+waitIfBatch()
 

=== modified file 'examples/funnel.py'
--- examples/funnel.py	2012-06-28 19:34:29 +0000
+++ examples/funnel.py	2013-03-28 10:53:06 +0000
@@ -13,7 +13,7 @@
 
 sp=pack.SpherePack()
 sp.makeCloud(Vector3(-1,-9,30),Vector3(1,-13,32),.2,rRelFuzz=.3)
-O.bodies.append([utils.sphere(c,r) for c,r in sp])
+O.bodies.append([sphere(c,r) for c,r in sp])
 
 O.engines=[
 	ForceResetter(), 
@@ -27,7 +27,7 @@
 	NewtonIntegrator(gravity=(0,0,-9.81)),
 	VTKRecorder(iterPeriod=100,recorders=['spheres','facets','colors'],fileName='/tmp/p1-')
 ]
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 
 
 from yade import qt

=== modified file 'examples/grids/Simple_Grid_Falling.py'
--- examples/grids/Simple_Grid_Falling.py	2012-10-16 13:02:39 +0000
+++ examples/grids/Simple_Grid_Falling.py	2013-03-28 16:15:54 +0000
@@ -1,8 +1,7 @@
 # encoding: utf-8
 
-from yade import utils,pack,geom,qt
+from yade import pack,geom,qt
 from pylab import *
-import math
 qt.View()
 
 
@@ -34,14 +33,14 @@
 #Create all nodes first :
 for i in range(0,nbL):
 	for j in range(0,nbl):
-		nodesIds.append( O.bodies.append(utils.gridNode([i*L/nbL,j*l/nbl,0],r,wire=False,fixed=False,material='spheremat',color=color)) )
+		nodesIds.append( O.bodies.append(gridNode([i*L/nbL,j*l/nbl,0],r,wire=False,fixed=False,material='spheremat',color=color)) )
 
 #Create connection between the nodes
 for i in range(0,len(nodesIds)):
 	for j in range(i+1,len(nodesIds)):
 		dist=(O.bodies[i].state.pos - O.bodies[j].state.pos).norm()
 		if(dist<=L/nbL*1.01):
-			O.bodies.append( utils.gridConnection(i,j,r,color=color) )
+			O.bodies.append( gridConnection(i,j,r,color=color) )
 
 #Set a fixed node
 O.bodies[0].dynamic=False

=== modified file 'examples/gts-horse/gts-horse.py'
--- examples/gts-horse/gts-horse.py	2012-10-05 14:33:55 +0000
+++ examples/gts-horse/gts-horse.py	2013-03-28 11:04:00 +0000
@@ -48,7 +48,7 @@
 	PyRunner(iterPeriod=1000,command='timing.stats(); O.pause();'),
 	PyRunner(iterPeriod=10,command='addPlotData()')
 ]
-O.dt=.7*utils.PWaveTimeStep()
+O.dt=.7*PWaveTimeStep()
 O.saveTmp()
 O.timingEnabled=True
 O.trackEnergy=True

=== modified file 'examples/hdaps.py'
--- examples/hdaps.py	2012-10-05 14:33:55 +0000
+++ examples/hdaps.py	2013-03-28 10:53:06 +0000
@@ -4,7 +4,7 @@
 
 O.bodies.append(
 	geom.facetBox(center=(0,0,.1),extents=(.5,.5,.1),wallMask=31,color=(0,0,1))+
-	[utils.sphere((0,0,.1),.04,color=(1,1,1))]
+	[sphere((0,0,.1),.04,color=(1,1,1))]
 )
 
 O.engines=[
@@ -14,7 +14,7 @@
 	HdapsGravityEngine(calibrate=(-495,-495),calibrated=True,zeroGravity=(0,0,-1)),
 	NewtonIntegrator(damping=.3),
 ]
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 
 import yade.qt
 yade.qt.View()

=== modified file 'examples/mill.py'
--- examples/mill.py	2012-06-28 19:34:29 +0000
+++ examples/mill.py	2013-03-28 10:53:06 +0000
@@ -45,7 +45,7 @@
 # make the caps less comfortably, but looking better as two triangle couples over the mill
 mrs2=millRad*sqrt(2)
 cap1,cap2=[Vector3(0,0,mrs2),Vector3(0,-mrs2,0),Vector3(0,0,-mrs2)],[Vector3(0,0,mrs2),Vector3(0,0,-mrs2),Vector3(0,mrs2,0)] # 2 triangles at every side
-for xx in -.5*millDp,.5*millDp: millIds+=O.bodies.append([utils.facet([p+Vector3(xx,0,0) for p in cap1],color=(0,0,0)),utils.facet([p+Vector3(xx,0,0) for p in cap2],color=(0,0,0))])
+for xx in -.5*millDp,.5*millDp: millIds+=O.bodies.append([facet([p+Vector3(xx,0,0) for p in cap1],color=(0,0,0)),facet([p+Vector3(xx,0,0) for p in cap2],color=(0,0,0))])
 
 # define domains for initial cloud of red and blue spheres
 packHt=.8*millRad # size of the area
@@ -54,11 +54,11 @@
 for i in (0,1): # red and blue spheres
 	sp=pack.SpherePack(); bb=bboxes[i]; vol=(bb[1][0]-bb[0][0])*(bb[1][1]-bb[0][1])*(bb[1][2]-bb[0][2])
 	sp.makeCloud(bb[0],bb[1],sphRad,sphRadFuzz,int(.25*vol/((4./3)*pi*sphRad**3)),False)
-	O.bodies.append([utils.sphere(s[0],s[1],color=colors[i]) for s in sp])
+	O.bodies.append([sphere(s[0],s[1],color=colors[i]) for s in sp])
 
 print "Numer of grains",len(O.bodies)-len(millIds)
 
-O.dt=.5*utils.PWaveTimeStep()
+O.dt=.5*PWaveTimeStep()
 
 O.engines=[
 	ForceResetter(),
@@ -79,4 +79,4 @@
 v=qt.View()
 v.eyePosition=(3,.8,.96); v.upVector=(-.4,-.4,.8); v.viewDir=(-.9,-.25,-.3); v.axes=True; v.sceneRadius=1.9
 #O.run(20000); O.wait()
-#utils.encodeVideoFromFrames(snapshooter['savedSnapshots'],out='/tmp/mill.ogg',fps=30)
+#encodeVideoFromFrames(snapshooter['savedSnapshots'],out='/tmp/mill.ogg',fps=30)

=== modified file 'examples/normalInelasticity-test.py'
--- examples/normalInelasticity-test.py	2012-10-05 14:33:55 +0000
+++ examples/normalInelasticity-test.py	2013-03-28 10:53:06 +0000
@@ -19,8 +19,8 @@
 #O.materials.append(FrictMat(young=10e9,poisson=.25,frictionAngle=0.5,density=1e3))
 
 #Def of the bodies of the simulations : 2 spheres, with names which will be useful after
-O.bodies.append(utils.sphere([0,0,0], 1, fixed=True, wire=False, color=None, highlight=False)) #'Materiau1', as the latest material defined, will be used
-O.bodies.append(utils.sphere([0,2,0], 1, fixed=True, wire=False, color=None, highlight=False))
+O.bodies.append(sphere([0,0,0], 1, fixed=True, wire=False, color=None, highlight=False)) #'Materiau1', as the latest material defined, will be used
+O.bodies.append(sphere([0,2,0], 1, fixed=True, wire=False, color=None, highlight=False))
 
 lowerSphere=O.bodies[0]
 upperSphere=O.bodies[1]

=== modified file 'examples/not-working/Se3Interpolator.py'
--- examples/not-working/Se3Interpolator.py	2012-03-13 15:23:04 +0000
+++ examples/not-working/Se3Interpolator.py	2013-03-28 11:04:54 +0000
@@ -14,7 +14,7 @@
 """
 
 O.bodies.append([
-	utils.sphere([0,0,0],radius=.5),
+	sphere([0,0,0],radius=.5),
 ])
 
 O.engines=[

=== modified file 'examples/not-working/facet-topo.py'
--- examples/not-working/facet-topo.py	2012-04-13 16:27:00 +0000
+++ examples/not-working/facet-topo.py	2013-03-28 11:04:54 +0000
@@ -18,16 +18,16 @@
 # most simple case: no touch at all
 if 1:
 	O.bodies.append([
-		utils.facet([(0,0,0),(1,0,0),(0,1,0)]),
-		utils.facet([(0,0,1),(1,0,1),(0,1,1)]),
+		facet([(0,0,0),(1,0,0),(0,1,0)]),
+		facet([(0,0,1),(1,0,1),(0,1,1)]),
 	])
 	O.step();
 	assert(topo['commonEdgesFound']==0)
 if 1:
 	O.bodies.clear()
 	O.bodies.append([
-		utils.facet([(0,0,0),(1,0,0),(0,1,0)]),
-		utils.facet([(1,1,0),(1,0,0),(0,1,0)]),
+		facet([(0,0,0),(1,0,0),(0,1,0)]),
+		facet([(1,1,0),(1,0,0),(0,1,0)]),
 	])
 	O.step()
 	assert(O.bodies[0].shape['edgeAdjIds'][1]==0 and O.bodies[1].shape['edgeAdjIds'][1]==1)
@@ -35,8 +35,8 @@
 if 1:
 	O.bodies.clear()
 	O.bodies.append([
-		utils.facet([(0,0,0),(1,0,0),(0,1,0)]),
-		utils.facet([(1,1,1),(1,0,0),(0,1,0)]),
+		facet([(0,0,0),(1,0,0),(0,1,0)]),
+		facet([(1,1,1),(1,0,0),(0,1,0)]),
 	])
 	O.step()
 	assert(O.bodies[0].shape['edgeAdjIds'][1]==0 and O.bodies[1].shape['edgeAdjIds'][1]==1)
@@ -58,8 +58,8 @@
 		return rr*cos(phi),rr*sin(phi),-r*cos(theta)
 	for i in range(0,nPoly/2):
 		for j in range(0,nPoly):
-			if i!=0: O.bodies.append(utils.facet([sphPt(i,j),sphPt(i,j+1),sphPt(i+1,j)]))
-			if i!=nPoly/2-1: O.bodies.append(utils.facet([sphPt(i+1,j),sphPt(i,j+1),sphPt(i+1,j+1)]))
+			if i!=0: O.bodies.append(facet([sphPt(i,j),sphPt(i,j+1),sphPt(i+1,j)]))
+			if i!=nPoly/2-1: O.bodies.append(facet([sphPt(i+1,j),sphPt(i,j+1),sphPt(i+1,j+1)]))
 	print 'Sphere created, has',len(O.bodies),'facets'
 	O.step()
 	assert(topo['commonVerticesFound']==nPoly*(nPoly/2-1)+2)

=== modified file 'examples/not-working/insertion-sort-collider.py'
--- examples/not-working/insertion-sort-collider.py	2012-06-28 19:34:29 +0000
+++ examples/not-working/insertion-sort-collider.py	2013-03-28 11:04:54 +0000
@@ -11,16 +11,16 @@
 ]
 mat=O.materials.append(FrictMat(young=1e3,poisson=.2,density=1000,frictionAngle=20))
 O.bodies.append([
-	utils.facet([[-1,-1,0],[1,-1,0],[0,1,0]],fixed=True,color=[1,0,0],material=mat),
-	utils.facet([[1,-1,0],[0,1,0,],[1,.5,.5]],fixed=True,material=mat)
+	facet([[-1,-1,0],[1,-1,0],[0,1,0]],fixed=True,color=[1,0,0],material=mat),
+	facet([[1,-1,0],[0,1,0,],[1,.5,.5]],fixed=True,material=mat)
 ])
 import random
 if 1:
 	for i in range(0,100):
-		O.bodies.append(utils.sphere([random.gauss(0,1),random.gauss(0,1),random.uniform(1,2)],random.uniform(.02,.05),material=mat))
+		O.bodies.append(sphere([random.gauss(0,1),random.gauss(0,1),random.uniform(1,2)],random.uniform(.02,.05),material=mat))
 		O.bodies[len(O.bodies)-1].state.vel=Vector3(random.gauss(0,.1),random.gauss(0,.1),random.gauss(0,.1))
 else:
-	O.bodies.append(utils.sphere([0,0,.6],.5),material=mat)
+	O.bodies.append(sphere([0,0,.6],.5),material=mat)
 O.dt=1e-4
 O.saveTmp('init')
 
@@ -31,7 +31,7 @@
 	for collider in InsertionSortCollider(),PersistentTriangulationCollider(haveDistantTransient=True):
 		for i in range(2):
 			O.loadTmp('init')
-			utils.replaceCollider(collider)
+			replaceCollider(collider)
 			O.run(100,True)
 			timing.reset()
 			O.run(50000,True)

=== modified file 'examples/not-working/triax-identical-results.py'
--- examples/not-working/triax-identical-results.py	2012-03-13 15:23:04 +0000
+++ examples/not-working/triax-identical-results.py	2013-03-28 11:04:54 +0000
@@ -15,7 +15,7 @@
   File "/home/me/YADE/YADE3041/bin/yade-bzr3041", line 182, in runScript                                                             
     execfile(script,globals())                                                                                                       
   File "triax-identical-results.py", line 20, in <module>                                                                            
-    utils.spheresToFile(inSph)                                                                                                       
+    spheresToFile(inSph)                                                                                                       
 AttributeError: 'module' object has no attribute 'spheresToFile' 
 """
 
@@ -31,10 +31,10 @@
 else:
 	TriaxialTest(noFiles=True).load()
 	print "Using new initial configuration in",inSph
-	utils.spheresToFile(inSph)
+	spheresToFile(inSph)
 TriaxialTest(importFilename=inSph,noFiles=True).load()
 O.usesTimeStepper=False
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 #
 # uncomment this line to enable shear computation in ScGeom and then compare results with this line commented
 #
@@ -44,6 +44,6 @@
 	#	#	O.save('/tmp/a.%03d.xml'%O.iter)
 	#	O.step()
 	O.run(2000,True)
-	utils.spheresToFile(outSph)
+	spheresToFile(outSph)
 	print "Results saved to",outSph
 	#quit()

=== modified file 'examples/packs/packs.py'
--- examples/packs/packs.py	2012-04-25 07:07:00 +0000
+++ examples/packs/packs.py	2013-03-28 16:15:54 +0000
@@ -1,7 +1,6 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 from yade import pack,ymport,export,geom,bodiesHandling
-import math
 
 """ This script demonstrates how to use 2 components of creating packings:
 
@@ -31,10 +30,10 @@
 	pack.regularHexa(
 		(pack.inSphere((0,0,4),2)-pack.inSphere((0,-2,5),2)) & pack.notInNotch(centerPoint=(0,0,4),edge=(0,1,0),normal=(-1,1,-1),aperture=.2)
 		,radius=rad,gap=gap,color=(0,1,0),material=0) # head
-	+[utils.sphere((.8,1.9,5),radius=.2,color=(.6,.6,.6),material=0),utils.sphere((-.8,1.9,5),radius=.2,color=(.6,.6,.6),material=0),utils.sphere((0,2.4,4),radius=.4,color=(1,0,0),material=0)] # eyes and nose
+	+[sphere((.8,1.9,5),radius=.2,color=(.6,.6,.6),material=0),sphere((-.8,1.9,5),radius=.2,color=(.6,.6,.6),material=0),sphere((0,2.4,4),radius=.4,color=(1,0,0),material=0)] # eyes and nose
 	+pack.regularHexa(pack.inCylinder((-1,2.2,3.3),(1,2.2,3.3),2*rad),radius=rad,gap=gap/3,color=(0.929,0.412,0.412),material=0) #mouth
 )
-groundId=O.bodies.append(utils.facet([(12,0,-6),(0,12,-6,),(-12,-12,-6)],dynamic=False)) # ground
+groundId=O.bodies.append(facet([(12,0,-6),(0,12,-6,),(-12,-12,-6)],dynamic=False)) # ground
 
 for part in [
 	pack.regularHexa (
@@ -48,36 +47,36 @@
 
 
 # Example of geom.facetBox usage 
-oriBody = Quaternion(Vector3(0,0,1),(math.pi/3))
+oriBody = Quaternion(Vector3(0,0,1),(pi/3))
 O.bodies.append(geom.facetBox((12,0,-6+0.9),(1,0.7,0.9),oriBody,**kwBoxes))
 
-oriBody = Quaternion(Vector3(0,0,1),(math.pi/2))
+oriBody = Quaternion(Vector3(0,0,1),(pi/2))
 O.bodies.append(geom.facetBox((0,12,-6+0.9),(1,0.7,0.9),oriBody,**kwBoxes))
 
-oriBody = Quaternion(Vector3(0,0,1),(math.pi))
+oriBody = Quaternion(Vector3(0,0,1),(pi))
 O.bodies.append(geom.facetBox((-12,-12,-6+0.9),(1,0.7,0.9),oriBody,**kwBoxes))
 
 # Example of geom.facetParallelepiped usage 
-oriBody = Quaternion(Vector3(0,0,1),(math.pi/3))
+oriBody = Quaternion(Vector3(0,0,1),(pi/3))
 O.bodies.append(geom.facetParallelepiped(center=Vector3(12,0,-6+2.7),extents=Vector3(1,0.7,0.9),height=0.5, orientation=oriBody,**kwBoxes))
 
-oriBody = Quaternion(Vector3(0,0,1),(math.pi/2))
+oriBody = Quaternion(Vector3(0,0,1),(pi/2))
 O.bodies.append(geom.facetParallelepiped(center=Vector3(0,12,-6+2.7),extents=Vector3(1,0.7,0.9),height=0.5, orientation=oriBody,**kwBoxes))
 
-oriBody = Quaternion(Vector3(0,0,1),(math.pi))
+oriBody = Quaternion(Vector3(0,0,1),(pi))
 O.bodies.append(geom.facetParallelepiped(center=Vector3(-12,-12,-6+2.7),extents=Vector3(1,0.7,0.9),height=0.5, orientation=oriBody,**kwBoxes))
 
 # Example of geom.facetCylinder, facetHelix and RotationEngine usage example
-oriBody = Quaternion(Vector3(1,0,0),(math.pi/2.0))
-rotateIDs=O.bodies.append(geom.facetHelix((-7.0,-6.0,-5.0),radiusOuter=2.0,radiusInner=0.1,pitch=2.0,orientation=oriBody,segmentsNumber=50,angleRange=[math.pi*8.0,0],**kwBoxes))
+oriBody = Quaternion(Vector3(1,0,0),(pi/2.0))
+rotateIDs=O.bodies.append(geom.facetHelix((-7.0,-6.0,-5.0),radiusOuter=2.0,radiusInner=0.1,pitch=2.0,orientation=oriBody,segmentsNumber=50,angleRange=[pi*8.0,0],**kwBoxes))
 O.bodies.append(geom.facetCylinder((-7.0,-12.0,-5.0),radius=2.0,height=7.0,orientation=oriBody,segmentsNumber=10,wallMask=4,**kwMeshes))
-O.bodies.append(geom.facetCylinder((-7.0,-7.0,-5.0),radius=2.0,height=4.0,segmentsNumber=10,wallMask=4,angleRange=[-math.pi*0.2,math.pi*1.2],**kwMeshes))
+O.bodies.append(geom.facetCylinder((-7.0,-7.0,-5.0),radius=2.0,height=4.0,segmentsNumber=10,wallMask=4,angleRange=[-pi*0.2,pi*1.2],**kwMeshes))
 
-oriBody = Quaternion(Vector3(0,0,1),(math.pi/2))
+oriBody = Quaternion(Vector3(0,0,1),(pi/2))
 O.bodies.append(ymport.gmsh('cone.mesh',orientation=oriBody,**kwMeshes))#generates facets from the mesh file
 
 SpheresID=[]
-oriBody = Quaternion(Vector3(0,0,1),(math.pi/2))
+oriBody = Quaternion(Vector3(0,0,1),(pi/2))
 SpheresID+=O.bodies.append(ymport.gengeoFile('LSMGenGeo.geo',shift=Vector3(-7.0,-7.0,0.0),scale=1.0,orientation=oriBody,color=(1,0,1),**kw))
 
 #Demonstration of spheresPackDimensions function. The "Edge" particles are colored with blue color
@@ -88,7 +87,7 @@
 
 #Example of bodiesHandling.spheresModify()
 hat=O.bodies.append(pack.regularOrtho(pack.inCylinder((0,0,6),(0,0,7),20*rad),radius=0.2,gap=0,color=(1,0,0))) # hat
-oriBody = Quaternion(Vector3(0,1,0),(math.pi/8))
+oriBody = Quaternion(Vector3(0,1,0),(pi/8))
 hat_upper=O.bodies.append(bodiesHandling.spheresModify(hat,shift=(0.0,0.0,1.4),scale=0.7,orientation=oriBody,copy=True))		#Duplicate the "heart", shifting, scaling and rotating it
 
 #change the color of upper part of the hat
@@ -111,7 +110,7 @@
 O.bodies.append(geom.facetBox((-15,5,-5),(2,2,2),wallMask=15,**kwMeshes))
 vibrationRotationPlate = O.bodies.append(geom.facetBox((-15,5,-5),(2,2,2),wallMask=16,**kwBoxes))
 
-O.bodies.append(utils.wall((0,0,-10),axis=2))
+O.bodies.append(wall((0,0,-10),axis=2))
 
 try:
 	from yade import qt
@@ -139,7 +138,7 @@
 	HarmonicRotationEngine(A=0.2, f=20.0, fi = pi, rotationAxis=[1.0,0.0,0.0], rotateAroundZero = True, zeroPoint = [-15.0,3.0,-7.0], ids = vibrationRotationPlate),
 	BoxFactory(maxParticles=300, extents=(1.0,1.0,1.0),center=(0.0,12.0,0.0),vMin=200.0,vMax=250.0,
 		PSDsizes=(0.1, 0.2, 0.3, 0.5, 0.7), PSDcum=(0.1, 0.5, 0.8, 1.0), PSDcalculateMass=True, exactDiam=False,
-		vAngle=math.pi/3.0,massFlowRate=50000.0,normal=(0.0,0.0,1.0),label='factory',mask=7,silent=True,stopIfFailed=False)
+		vAngle=pi/3.0,massFlowRate=50000.0,normal=(0.0,0.0,1.0),label='factory',mask=7,silent=True,stopIfFailed=False)
 ]
 '''
 Boxfactory is an example of usage SpheresFactory. Produces PSD-dispersion:
@@ -153,7 +152,7 @@
 '''
 
 # we don't care about physical accuracy here, (over)critical step is fine as long as the simulation doesn't explode
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.saveTmp()
 O.timingEnabled=True
 #O.run(10000,True)

=== modified file 'examples/periodic-compress.py'
--- examples/periodic-compress.py	2012-10-05 14:33:55 +0000
+++ examples/periodic-compress.py	2013-03-28 10:53:06 +0000
@@ -11,7 +11,7 @@
 p=pack.SpherePack()
 p.makeCloud(Vector3(0,0,0),Vector3(20,20,10),1,.5,700,True)
 for sph in p:
-	O.bodies.append(utils.sphere(sph[0],sph[1]))
+	O.bodies.append(sphere(sph[0],sph[1]))
 
 
 O.timingEnabled=True
@@ -26,7 +26,7 @@
 	PeriIsoCompressor(charLen=.5,stresses=[-50e9,-1e8],doneHook="print 'FINISHED'; O.pause() ",keepProportions=True),
 	NewtonIntegrator(damping=.4)
 ]
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.saveTmp()
 #print O.cell.refSize
 from yade import qt; qt.Controller(); qt.View()
@@ -45,4 +45,4 @@
 #sp.cellFill((30,30,30))
 #print sp.cellSize
 #for s in sp:
-#	O.bodies.append(utils.sphere(s[0],s[1]))
+#	O.bodies.append(sphere(s[0],s[1]))

=== modified file 'examples/periodic-grow.py'
--- examples/periodic-grow.py	2012-10-05 14:33:55 +0000
+++ examples/periodic-grow.py	2013-03-28 10:53:06 +0000
@@ -15,12 +15,12 @@
 ]
 import random
 for i in xrange(250):
-	O.bodies.append(utils.sphere(Vector3(10*random.random(),10*random.random(),10*random.random()),.5+random.random()))
+	O.bodies.append(sphere(Vector3(10*random.random(),10*random.random(),10*random.random()),.5+random.random()))
 cubeSize=20
 # absolute positioning of the cell is not important
 O.periodic=True
 O.cell.setBox(cubeSize,cubeSize,cubeSize)
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.saveTmp()
 from yade import qt
 qt.Controller(); qt.View()
@@ -32,8 +32,8 @@
 
 for i in range(0,25):
 	O.run(2000,True)
-	F,stiff=utils.totalForceInVolume()
+	F,stiff=totalForceInVolume()
 	dim=O.cell.refSize; A=Vector3(dim[1]*dim[2],dim[0]*dim[2],dim[0]*dim[1])
 	avgStress=sum([F[i]/A[i] for i in 0,1,2])/3.
-	print 'strain',(cubeSize-dim[0])/cubeSize,'avg. stress ',avgStress,'unbalanced ',utils.unbalancedForce()
+	print 'strain',(cubeSize-dim[0])/cubeSize,'avg. stress ',avgStress,'unbalanced ',unbalancedForce()
 #O.timingEnabled=True; timing.reset(); O.run(200000,True); timing.stats()

=== modified file 'examples/periodicSandPile.py'
--- examples/periodicSandPile.py	2012-03-12 20:00:24 +0000
+++ examples/periodicSandPile.py	2013-03-28 10:53:06 +0000
@@ -18,16 +18,16 @@
 		    0, 0, width)
 
 O.materials.append(FrictMat(density=1,young=1e5,poisson=0.3,frictionAngle=radians(30),label='boxMat'))
-lowBox = utils.box( center=(length/2.0,height-thickness/2.0,width/2.0), extents=(length*1000.0,thickness/2.0,width*1000.0) ,fixed=True,wire=False)
+lowBox = box( center=(length/2.0,height-thickness/2.0,width/2.0), extents=(length*1000.0,thickness/2.0,width*1000.0) ,fixed=True,wire=False)
 O.bodies.append(lowBox)
 
 radius=0.01
 O.materials.append(FrictMat(density=1000,young=1e4,poisson=0.3,frictionAngle=radians(30),label='sphereMat'))
 sp=pack.SpherePack()
 sp.makeCloud((0.*length,height+1.2*radius,0.25*width),(0.5*length,2*height-1.2*radius,0.75*width),-1,.2,2000,periodic=True)
-O.bodies.append([utils.sphere(s[0],s[1],color=(0.6+0.15*rand(),0.5+0.15*rand(),0.15+0.15*rand())) for s in sp])
+O.bodies.append([sphere(s[0],s[1],color=(0.6+0.15*rand(),0.5+0.15*rand(),0.15+0.15*rand())) for s in sp])
 
-O.dt=0.2*utils.PWaveTimeStep()
+O.dt=0.2*PWaveTimeStep()
 O.usesTimeStepper=True
 newton=NewtonIntegrator(damping=0.6,gravity=(0,-10,0))
 

=== modified file 'examples/ring2d/ringCundallDamping.py'
--- examples/ring2d/ringCundallDamping.py	2012-06-28 19:34:29 +0000
+++ examples/ring2d/ringCundallDamping.py	2013-03-28 11:06:34 +0000
@@ -1,7 +1,6 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 
-from yade import utils
 from yade import ymport
 
 sphereRadius=0.05
@@ -18,7 +17,7 @@
 					x = cylinderOrigin[0]+2*r*sphereRadius*cos(dfi*a)
 					y = cylinderOrigin[1]+2*r*sphereRadius*sin(dfi*a)
 					z = cylinderOrigin[2]+h*2*sphereRadius
-					s=utils.sphere([x,y*cos(cylinderSlope)+z*sin(cylinderSlope),z*cos(cylinderSlope)-y*sin(cylinderSlope)],sphereRadius)
+					s=sphere([x,y*cos(cylinderSlope)+z*sin(cylinderSlope),z*cos(cylinderSlope)-y*sin(cylinderSlope)],sphereRadius)
 					O.bodies.append(s)
 					spheresCount+=1
 	return spheresCount
@@ -55,7 +54,7 @@
 for b in O.bodies:
     if isinstance(b.shape,Sphere): b.state.blockedDOFs='z' # blocked movement along Z
 
-O.dt=0.02*utils.PWaveTimeStep()
+O.dt=0.02*PWaveTimeStep()
 
 O.saveTmp('init');
 

=== modified file 'examples/ring2d/ringSimpleViscoelastic.py'
--- examples/ring2d/ringSimpleViscoelastic.py	2012-02-16 16:11:06 +0000
+++ examples/ring2d/ringSimpleViscoelastic.py	2013-03-28 11:06:34 +0000
@@ -1,7 +1,6 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 
-from yade import utils
 from yade import ymport
 
 ## Omega
@@ -16,7 +15,7 @@
 es = 0.3
 
 ## Import wall's geometry
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) # **params sets kn, cn, ks, cs
 sphereMat=O.materials.append(ViscElMat(density=Density,frictionAngle=frictionAngle,**params))
 
@@ -31,7 +30,7 @@
 					x = cylinderOrigin[0]+2*r*sphereRadius*cos(dfi*a)
 					y = cylinderOrigin[1]+2*r*sphereRadius*sin(dfi*a)
 					z = cylinderOrigin[2]+h*2*sphereRadius
-					s=utils.sphere([x,y*cos(cylinderSlope)+z*sin(cylinderSlope),z*cos(cylinderSlope)-y*sin(cylinderSlope)],sphereRadius,material=sphereMat)
+					s=sphere([x,y*cos(cylinderSlope)+z*sin(cylinderSlope),z*cos(cylinderSlope)-y*sin(cylinderSlope)],sphereRadius,material=sphereMat)
 					o.bodies.append(s)
 					spheresCount+=1
 	return spheresCount

=== modified file 'examples/rod-penetration/model.py'
--- examples/rod-penetration/model.py	2012-06-28 19:34:29 +0000
+++ examples/rod-penetration/model.py	2013-03-28 11:08:11 +0000
@@ -1,7 +1,6 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 
-from yade import utils
 import random
 from yade import ymport
 
@@ -31,11 +30,11 @@
 			if (i==0 or i==nbSpheres[0]-1 or j==nbSpheres[1]-1 or k==0 or k==nbSpheres[2]-1):
 				fixed = True
 				color=[0.21,0.22,0.1]
-			O.bodies.append(utils.sphere([x,y,z],r,color=color,fixed=fixed))
+			O.bodies.append(sphere([x,y,z],r,color=color,fixed=fixed))
 print "done\n"
 
 ## Estimate time step
-#O.dt=utils.PWaveTimeStep()
+#O.dt=PWaveTimeStep()
 O.dt=0.0001
 
 

=== added file 'examples/simple-scene/simple-scene-default-engines.py'
--- examples/simple-scene/simple-scene-default-engines.py	1970-01-01 00:00:00 +0000
+++ examples/simple-scene/simple-scene-default-engines.py	2012-12-06 19:11:35 +0000
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+## Demonstrate scene construction using the default list of engines
+## Note that it is no longer necessary to define O.dt
+## See simple-scene.py for the complete version with explicit engines definition 
+
+typedEngine("NewtonIntegrator").gravity=(0,0,-9.81)
+typedEngine("NewtonIntegrator").damping=0.1
+O.bodies.append(box(center=[0,0,0],extents=[.5,.5,.5],color=[0,0,1],fixed=True))
+O.bodies.append(sphere([0,0,2],1,color=[0,1,0]))
+O.save('/tmp/a.xml.bz2');

=== modified file 'examples/simple-scene/simple-scene-energy-tracking.py'
--- examples/simple-scene/simple-scene-energy-tracking.py	2012-03-12 20:00:24 +0000
+++ examples/simple-scene/simple-scene-energy-tracking.py	2013-03-28 14:28:39 +0000
@@ -47,17 +47,16 @@
 		[Ip2_CohFrictMat_CohFrictMat_CohFrictPhys()],
 		[law]
 	),
-	GlobalStiffnessTimeStepper(active=1,timeStepUpdateInterval=50),
+	GlobalStiffnessTimeStepper(active=1,timeStepUpdateInterval=50,timestepSafetyCoefficient=.0001),
 	NewtonIntegrator(damping=damping,kinSplit=True,gravity=(0,0,-g)),
 	PyRunner(iterPeriod=20,command='myAddPlotData()')
 ]
 
-from yade import utils
-O.bodies.append(utils.box(center=[0,0,0],extents=[.5,.5,.5],fixed=True,color=[1,0,0],material='granular_material'))
-O.bodies.append(utils.sphere([0,0,2],1,color=[0,1,0],material='granular_material'))
+O.bodies.append(box(center=[0,0,0],extents=[.5,.5,.5],fixed=True,color=[1,0,0],material='granular_material'))
+O.bodies.append(sphere([0,0,2],1,color=[0,1,0],material='granular_material'))
 if(two_spheres):
-	O.bodies.append(utils.sphere([0,0,4],1,color=[0,1,0],material='granular_material'))
-O.dt=.002*utils.PWaveTimeStep()
+	O.bodies.append(sphere([0,0,4],1,color=[0,1,0],material='granular_material'))
+O.dt=.002*PWaveTimeStep()
 O.bodies[1].state.angVel[1]=angVel
 if(rotate_in_two_directions):
 	O.bodies[1].state.angVel[2]=angVel
@@ -66,7 +65,6 @@
 ##### now the part pertaining to plots #####
 ############################################
 
-from math import *
 from yade import plot
 ## we will have 2 plots:
 ## 1. t as function of i (joke test function)
@@ -109,7 +107,7 @@
 	if(two_spheres):## for more bodies we better use the energy tracker, because it's tracking all bodies
 		E_kin_translation = E_tracker['kinTrans']
 		E_kin_rotation    = E_tracker['kinRot']
-		#E_pot             = E_tracker['gravWork'] 	#will cause a python crash!!!
+		E_pot             = E_tracker['gravWork']
 
 	else: ## for one sphere we can just calculate, and it will be correct
 		sph=O.bodies[1]
@@ -148,7 +146,7 @@
 plot.plot(subPlots=False)
 #from yade import qt
 #qt.View()
-O.run(int(2./O.dt));
+O.run(int(20./O.dt));
 #plot.saveGnuplot('/tmp/a')
 ## you can also access the data in plot.data['t'], etc, under the labels they were saved.
 

=== modified file 'examples/simple-scene/simple-scene-plot.py'
--- examples/simple-scene/simple-scene-plot.py	2012-10-05 14:33:55 +0000
+++ examples/simple-scene/simple-scene-plot.py	2013-03-28 16:15:54 +0000
@@ -19,17 +19,15 @@
 	### whichever comes soones. virtTimeLim attribute is unset, hence virtual time period is not taken into account.
 	PyRunner(iterPeriod=20,command='myAddPlotData()')
 ]
-from yade import utils
-O.bodies.append(utils.box(center=[0,0,0],extents=[.5,.5,.5],fixed=True,color=[1,0,0]))
-O.bodies.append(utils.sphere([0,0,2],1,color=[0,1,0]))
-O.dt=.002*utils.PWaveTimeStep()
+O.bodies.append(box(center=[0,0,0],extents=[.5,.5,.5],fixed=True,color=[1,0,0]))
+O.bodies.append(sphere([0,0,2],1,color=[0,1,0]))
+O.dt=.002*PWaveTimeStep()
 
 
 ############################################
 ##### now the part pertaining to plots #####
 ############################################
 
-from math import *
 from yade import plot
 ## we will have 2 plots:
 ## 1. t as function of i (joke test function)

=== modified file 'examples/simple-scene/simple-scene.py'
--- examples/simple-scene/simple-scene.py	2012-03-12 20:00:24 +0000
+++ examples/simple-scene/simple-scene.py	2013-03-28 09:58:33 +0000
@@ -50,7 +50,8 @@
 
 ## The yade.utils module contains some handy functions, like yade.utils.box and yade.utils.sphere.
 ## After this import, they will be accessible as utils.box and utils.sphere.
-from yade import utils
+### UPDATE: utils is loaded automatically, no longer need to import
+#from yade import utils
 
 ## create bodies in the simulation: one box in the origin and one floating above it.
 ##
@@ -59,18 +60,18 @@
 ## * center: position of the center of the box
 ## * dynamic: it is not dynamic, i.e. will not move during simulation, even if forces are applied to it
 
-o.bodies.append(utils.box(center=[0,0,0],extents=[.5,.5,.5],color=[0,0,1],fixed=True))
+o.bodies.append(box(center=[0,0,0],extents=[.5,.5,.5],color=[0,0,1],fixed=True))
 
 ## The sphere
 ##
 ## * First two arguments are radius and center, respectively. They are used as "positional arguments" here:
 ## python will deduce based on where they are what they mean.
 ##
-## It could also be written without using utils.sphere - see gui/py/utils.py for the code of the utils.sphere function
-o.bodies.append(utils.sphere([0,0,2],1,color=[0,1,0]))
+## It could also be written without using sphere - see gui/py/utils.py for the code of the sphere function
+o.bodies.append(sphere([0,0,2],1,color=[0,1,0]))
 
 ## Estimate timestep from p-wave speed and multiply it by safety factor of .2
-o.dt=.01*utils.PWaveTimeStep()
+o.dt=.01*PWaveTimeStep()
 
 ## Save the scene to file, so that it can be loaded later. Supported extension are: .xml, .xml.gz, .xml.bz2.
 o.save('/tmp/a.xml.bz2');
@@ -78,7 +79,7 @@
 
 def onBodySelect(id):
 	print "Selected:",id
-	utils.highlightNone()
+	highlightNone()
 	for i in O.interactions.withBody(id):
 		O.bodies[i.id2 if i.id1==id else i.id1].shape.highlight=True
 		print i.id1,i.id2,i.phys,i.geom

=== modified file 'examples/simple-shear/simpleShear.py'
--- examples/simple-shear/simpleShear.py	2012-10-05 14:33:55 +0000
+++ examples/simple-shear/simpleShear.py	2013-03-28 11:09:16 +0000
@@ -33,17 +33,17 @@
 #Definition of bodies constituing the numerical model : six boxes corresponding to sids of the simple shear box, containing a particle samples
 pred=inAlignedBox((0,0,-0.02),(0.1,0.02,0.02))
 
-leftBox = utils.box( center=(-thickness/2.0,(height)/2.0,0), extents=(thickness/2.0,5*(height/2.0+thickness),width/2.0) ,fixed=True,wire=True)
-
-lowBox = utils.box( center=(length/2.0,-thickness/2.0,0), extents=(length/2.0,thickness/2.0,width/2.0) ,fixed=True,wire=True)
-
-rightBox = utils.box( center=(length+thickness/2.0,height/2.0,0), extents=(thickness/2.0,5*(height/2.0+thickness),width/2.0) ,fixed=True,wire=True)
-
-upBox = utils.box( center=(length/2.0,height+thickness/2.0,0), extents=(length/2.0,thickness/2.0,width/2.0) ,fixed=True,wire=True)
-
-behindBox = utils.box( center=(length/2.0,height/2.0,-width/2.0-thickness/2.0), extents=(2.5*length/2.0,height/2.0+thickness,thickness/2.0), fixed=True,wire=True)
-
-inFrontBox = utils.box( center=(length/2.0,height/2.0,width/2.0+thickness/2.0), extents=(2.5*length/2.0,height/2.0+thickness,thickness/2.0), fixed=True,wire=True)
+leftBox = box( center=(-thickness/2.0,(height)/2.0,0), extents=(thickness/2.0,5*(height/2.0+thickness),width/2.0) ,fixed=True,wire=True)
+
+lowBox = box( center=(length/2.0,-thickness/2.0,0), extents=(length/2.0,thickness/2.0,width/2.0) ,fixed=True,wire=True)
+
+rightBox = box( center=(length+thickness/2.0,height/2.0,0), extents=(thickness/2.0,5*(height/2.0+thickness),width/2.0) ,fixed=True,wire=True)
+
+upBox = box( center=(length/2.0,height+thickness/2.0,0), extents=(length/2.0,thickness/2.0,width/2.0) ,fixed=True,wire=True)
+
+behindBox = box( center=(length/2.0,height/2.0,-width/2.0-thickness/2.0), extents=(2.5*length/2.0,height/2.0+thickness,thickness/2.0), fixed=True,wire=True)
+
+inFrontBox = box( center=(length/2.0,height/2.0,width/2.0+thickness/2.0), extents=(2.5*length/2.0,height/2.0+thickness,thickness/2.0), fixed=True,wire=True)
 
 O.bodies.append([leftBox,lowBox,rightBox,upBox,behindBox,inFrontBox])
 
@@ -54,7 +54,7 @@
 
 sp=yade._packSpheres.SpherePack()
 sp.makeCloud(Vector3(0,0.0,-width/2.0),Vector3(length,height,width/2.0),rMean,.15)
-O.bodies.append([utils.sphere(s[0],s[1]) for s in sp])
+O.bodies.append([sphere(s[0],s[1]) for s in sp])
 
 
 #---- Def of the engines ----#
@@ -91,7 +91,7 @@
 #---- Compression ----
 O.engines = O.engines+[KinemCTDEngine(compSpeed=0.5,sigma_save=(),temoin_save=(),targetSigma=40000.0,LOG=False)]
 
-O.dt=.4*utils.PWaveTimeStep()
+O.dt=.4*PWaveTimeStep()
 print ''
 print 'Be patient, running in progress (the shear box is being compressed)'
 O.run(14000,True)

=== modified file 'examples/test/CundallStrackTest.py'
--- examples/test/CundallStrackTest.py	2012-04-30 23:31:20 +0000
+++ examples/test/CundallStrackTest.py	2013-03-28 11:13:12 +0000
@@ -10,11 +10,11 @@
 	NewtonIntegrator(damping = 0.01,gravity=[0,0,-9.81])
 ]
 
-from yade import utils
-
-O.bodies.append(utils.sphere([0,0,6],1,fixed=False, color=[0,1,0]))
-O.bodies.append(utils.sphere([0,0,0],1,fixed=True, color=[0,0,1]))
-O.dt=.2*utils.PWaveTimeStep()
+
+
+O.bodies.append(sphere([0,0,6],1,fixed=False, color=[0,1,0]))
+O.bodies.append(sphere([0,0,0],1,fixed=True, color=[0,0,1]))
+O.dt=.2*PWaveTimeStep()
 
 from yade import qt
 qt.Controller()

=== modified file 'examples/test/Damping_HM.py'
--- examples/test/Damping_HM.py	2012-03-12 20:02:11 +0000
+++ examples/test/Damping_HM.py	2013-03-28 16:15:54 +0000
@@ -3,7 +3,7 @@
 
 # Script to test the contact damping in HM (both in the normal and shear direction)
 
-from yade import utils
+
 
 #__________________________________________________________________
 # Geometry sphere and box
@@ -21,8 +21,8 @@
 
 # Append geometry and material
 O.materials.append(FrictMat(young=young,poisson=poisson,density=density,frictionAngle=frictionAngle))
-O.bodies.append(utils.box(center=center,extents=extents,fixed=True,wire=True)) # body id=0
-O.bodies.append(utils.sphere(p2,r2,fixed=True,wire=True)) # body id=1
+O.bodies.append(box(center=center,extents=extents,fixed=True,wire=True)) # body id=0
+O.bodies.append(sphere(p2,r2,fixed=True,wire=True)) # body id=1
 m_sphere=O.bodies[1].state.mass
 O.bodies[0].state.mass=m_sphere # set the mass of the box the same as the mass of the sphere
 O.bodies[1].state.blockedDOFs='XYZ' # block particles rotations
@@ -50,7 +50,7 @@
 
 #__________________________________________________________________
 # time step
-O.dt=.2*utils.PWaveTimeStep()
+O.dt=.2*PWaveTimeStep()
 O.saveTmp('init')
 
 #__________________________________________________________________
@@ -60,7 +60,6 @@
 
 #__________________________________________________________________
 # plot some results
-from math import *
 from yade import plot
 
 plot.labels=dict(Fn='$Normal\,force$',un='$Overlapping$',time='$Time$',time_='$Time$',Fs='$Shear\,force$',t='$Time$')

=== modified file 'examples/test/Dem3DofGeom.py'
--- examples/test/Dem3DofGeom.py	2012-03-13 15:23:04 +0000
+++ examples/test/Dem3DofGeom.py	2013-03-28 16:15:54 +0000
@@ -1,9 +1,9 @@
 "Script showing shear interaction between facet/wall and sphere."
 O.bodies.append([
-	#utils.sphere([0,0,0],1,dynamic=False,color=(0,1,0),wire=True),
-	utils.facet(([2,2,1],[-2,0,1],[2,-2,1]),fixed=True,color=(0,1,0),wire=False),
-	#utils.wall([0,0,1],axis=2,color=(0,1,0)),
-	utils.sphere([-1,0,2],1,fixed=False,color=(1,0,0),wire=True),
+	#sphere([0,0,0],1,dynamic=False,color=(0,1,0),wire=True),
+	facet(([2,2,1],[-2,0,1],[2,-2,1]),fixed=True,color=(0,1,0),wire=False),
+	#wall([0,0,1],axis=2,color=(0,1,0)),
+	sphere([-1,0,2],1,fixed=False,color=(1,0,0),wire=True),
 ])
 O.engines=[
 	ForceResetter(),
@@ -15,10 +15,9 @@
 		Ig2_Facet_Sphere_Dem3DofGeom(),
 		Ig2_Wall_Sphere_Dem3DofGeom()
 	]),
-	#GravityEngine(gravity=(0,0,-10))
 	RotationEngine(rotationAxis=[0,1,0],angularVelocity=10,ids=[1]),
 	TranslationEngine(translationAxis=[1,0,0],velocity=10,ids=[1]),
-	NewtonIntegrator()
+	NewtonIntegrator()#gravity=(0,0,-10))
 ]
 O.miscParams=[
 	Gl1_Dem3DofGeom_SphereSphere(normal=True,rolledPoints=True,unrolledPoints=True,shear=True,shearLabel=True),

=== modified file 'examples/test/WireMatPM/net-2part-displ-unloading.py'
--- examples/test/WireMatPM/net-2part-displ-unloading.py	2012-04-30 23:31:19 +0000
+++ examples/test/WireMatPM/net-2part-displ-unloading.py	2013-03-28 11:17:23 +0000
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 # encoding: utf-8
-from yade import utils, ymport, qt, plot
+from yade import  ymport, qt, plot
 
 ## definition of some colors for colored text output in terminal
 BLUE = '\033[94m'
@@ -38,8 +38,8 @@
 
 
 #### create boddies, default: dynamic=True
-O.bodies.append( utils.sphere([0,0,0], radius, wire=False, color=[1,0,0], highlight=False, material=netMat) )
-O.bodies.append( utils.sphere([0,a,0], radius, wire=False, color=[0,1,0], highlight=False, material=netMat) )
+O.bodies.append( sphere([0,0,0], radius, wire=False, color=[1,0,0], highlight=False, material=netMat) )
+O.bodies.append( sphere([0,a,0], radius, wire=False, color=[0,1,0], highlight=False, material=netMat) )
 
 FixedSphere=O.bodies[0]
 MovingSphere=O.bodies[1]

=== modified file 'examples/test/WireMatPM/net-2part-displ.py'
--- examples/test/WireMatPM/net-2part-displ.py	2012-04-30 23:31:19 +0000
+++ examples/test/WireMatPM/net-2part-displ.py	2013-03-28 11:17:23 +0000
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 # encoding: utf-8
-from yade import utils, ymport, qt, plot
+from yade import  ymport, qt, plot
 
 ## definition of some colors for colored text output in terminal
 BLUE = '\033[94m'
@@ -35,8 +35,8 @@
 
 
 #### create boddies, default: dynamic=True
-O.bodies.append( utils.sphere([0,0,0], radius, wire=False, color=[1,0,0], highlight=False, material=netMat, fixed=True) )
-O.bodies.append( utils.sphere([0,a,0], radius, wire=False, color=[0,1,0], highlight=False, material=netMat) )
+O.bodies.append( sphere([0,0,0], radius, wire=False, color=[1,0,0], highlight=False, material=netMat, fixed=True) )
+O.bodies.append( sphere([0,a,0], radius, wire=False, color=[0,1,0], highlight=False, material=netMat) )
 
 FixedSphere=O.bodies[0]
 MovingSphere=O.bodies[1]

=== modified file 'examples/test/WireMatPM/net-2part-strain.py'
--- examples/test/WireMatPM/net-2part-strain.py	2012-04-30 23:31:19 +0000
+++ examples/test/WireMatPM/net-2part-strain.py	2013-03-28 16:15:54 +0000
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 # encoding: utf-8
-from yade import utils, ymport, qt
+from yade import  ymport, qt
 
 
 ## definition of some colors for colored text output in terminal
@@ -36,8 +36,8 @@
 
 
 #### create boddies, default: dynamic=True
-O.bodies.append( utils.sphere([0,0,0], radius, wire=False, color=[1,0,0], highlight=False, material=netMat) )
-O.bodies.append( utils.sphere([0,a,0], radius, wire=False, color=[0,1,0], highlight=False, material=netMat) )
+O.bodies.append( sphere([0,0,0], radius, wire=False, color=[1,0,0], highlight=False, material=netMat) )
+O.bodies.append( sphere([0,a,0], radius, wire=False, color=[0,1,0], highlight=False, material=netMat) )
 
 FixedSphere=O.bodies[0]
 MovingSphere=O.bodies[1]
@@ -47,7 +47,7 @@
 
 
 #### initialize values for UniaxialStrainer
-bb = utils.uniaxialTestFeatures(axis=1)
+bb = uniaxialTestFeatures(axis=1)
 negIds,posIds,axis,crossSectionArea=bb['negIds'],bb['posIds'],bb['axis'],bb['area']
 strainRateTension = 1./a
 setSpeeds = True
@@ -82,7 +82,6 @@
 #O.dt = 0.2*sqrt(particleMass/(2.*O.interactions[0,1].phys.kn))
 
 #### plot some results
-from math import *
 from yade import plot
 
 plot.plots={'un':('Fn',)}

=== modified file 'examples/test/batch/sim.py'
--- examples/test/batch/sim.py	2012-03-13 09:51:32 +0000
+++ examples/test/batch/sim.py	2013-03-28 11:15:45 +0000
@@ -1,6 +1,5 @@
 from yade import *
-from yade import utils
-utils.readParamsFromTable(unknownOk=True,
+readParamsFromTable(unknownOk=True,
 	important=6,
 	unimportant='foo',
 	this=-1,

=== modified file 'examples/test/beam-l6geom.py'
--- examples/test/beam-l6geom.py	2012-03-13 15:23:04 +0000
+++ examples/test/beam-l6geom.py	2013-03-28 11:13:12 +0000
@@ -5,13 +5,13 @@
 # radius, number and distance of spheres
 rad,num=1,6; dist=1.9999*rad
 # one arm
-O.bodies.append([utils.sphere((0,y,0),rad,wire=True) for y in numpy.arange(0,2*num-1,dist)])
+O.bodies.append([sphere((0,y,0),rad,wire=True) for y in numpy.arange(0,2*num-1,dist)])
 # the lateral arm
-O.bodies.append([utils.sphere((x,(num-1)*2*rad,0),rad,wire=True) for x in numpy.arange(dist,1+num/2,dist)])
+O.bodies.append([sphere((x,(num-1)*2*rad,0),rad,wire=True) for x in numpy.arange(dist,1+num/2,dist)])
 # support sphere
 O.bodies[0].state.blockedDOFs='xyzXYZ'
 # small dt to see in realtime how it swings; real critical is higher, but much less than p-wave
-O.dt=.01*utils.PWaveTimeStep() 
+O.dt=.01*PWaveTimeStep() 
 
 O.engines=[
 	ForceResetter(),
@@ -34,7 +34,7 @@
 	Gl1_L6Geom.phiScale=30; Gl1_L3Geom.uScale=20
 	#O.engines=O.engines+[
 	#	qt.SnapshotEngine(fileBase=O.tmpFilename(),label='snapper',iterPeriod=300,deadTimeout=20),
-	#	PyRunner(iterPeriod=330000,command='utils.makeVideo(snapper.snapshots,out="beam-l6geom.avi"); snapper.dead=True; O.pause()')
+	#	PyRunner(iterPeriod=330000,command='makeVideo(snapper.snapshots,out="beam-l6geom.avi"); snapper.dead=True; O.pause()')
 	#]
 except ImportError: pass
 O.run()

=== modified file 'examples/test/callback.py'
--- examples/test/callback.py	2012-03-13 15:23:04 +0000
+++ examples/test/callback.py	2013-03-28 11:13:12 +0000
@@ -1,7 +1,7 @@
 O.materials.append(FrictMat(young=30e9,poisson=.2,density=4000,frictionAngle=.5))
 O.bodies.append([
-	utils.sphere((0,0,0),1,fixed=True),
-	utils.sphere((0,0,2.1),1)
+	sphere((0,0,0),1,fixed=True),
+	sphere((0,0,2.1),1)
 ])
 O.engines=[
 	ForceResetter(),
@@ -13,9 +13,9 @@
 	),
 	NewtonIntegrator(label='newton',gravity=(0,0,-9.81))
 ]
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 
-disp=utils.typedEngine('InteractionLoop')
+disp=typedEngine('InteractionLoop')
 
 disp.callbacks=[SumIntrForcesCb()]
 #newton.callbacks=[SumBodyForcesCb()]

=== modified file 'examples/test/clump.py'
--- examples/test/clump.py	2012-03-13 15:23:04 +0000
+++ examples/test/clump.py	2013-03-28 11:13:12 +0000
@@ -12,18 +12,18 @@
 	NewtonIntegrator(damping=.2,exactAsphericalRot=True,gravity=[0,0,-9.81])
 ]
 # support
-O.bodies.append(utils.box([0,0,-1.5],[3,3,.2],fixed=True))
+O.bodies.append(box([0,0,-1.5],[3,3,.2],fixed=True))
 # stand-alone sphere
-O.bodies.append(utils.sphere([0,0,0],.5))
+O.bodies.append(sphere([0,0,0],.5))
 # clumps
 relPos=[(0,-.5,-.5),(0,.5,0),(.5,0,0),(0,0,.5)]
 coords=[(-2,0,0),(2,0,0),(0,2,0),(0,-2,0)]
 for i,cc in enumerate(coords):
 	# This shorthand command does something like this:
-	# O.bodies.appendClumped([utils.sphere(...),utils.sphere(...),utils.sphere(...)])
+	# O.bodies.appendClumped([sphere(...),sphere(...),sphere(...)])
 	# and returns tuple of clumpId,[bodyId1,bodyId2,bodyId3]
-	clump,spheres=O.bodies.appendClumped([utils.sphere([relPos[j][0]+coords[i][0],relPos[j][1]+coords[i][1],relPos[j][2]+coords[i][2]],.5) for j in range(0,i+1)])
+	clump,spheres=O.bodies.appendClumped([sphere([relPos[j][0]+coords[i][0],relPos[j][1]+coords[i][1],relPos[j][2]+coords[i][2]],.5) for j in range(0,i+1)])
 	print clump,spheres
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.saveTmp('init')
 

=== modified file 'examples/test/clumpPack.py'
--- examples/test/clumpPack.py	2012-03-13 15:23:04 +0000
+++ examples/test/clumpPack.py	2013-03-28 11:13:12 +0000
@@ -6,7 +6,7 @@
 print 'Generated # of clumps:',sp.makeClumpCloud((0,0,0),(15,15,15),[c1,c2],periodic=False)
 sp.toSimulation()
 
-O.bodies.append(utils.wall(position=0,axis=2))
+O.bodies.append(wall(position=0,axis=2))
 
 O.engines=[
 	#SubdomainBalancer(),
@@ -19,7 +19,7 @@
 	),
 	NewtonIntegrator(damping=.4,gravity=(0,0,-100))
 ]
-O.dt=.7*utils.PWaveTimeStep()
+O.dt=.7*PWaveTimeStep()
 O.saveTmp()
 O.step()
 

=== modified file 'examples/test/collider-stride-triax.py'
--- examples/test/collider-stride-triax.py	2012-04-13 16:27:00 +0000
+++ examples/test/collider-stride-triax.py	2013-03-28 11:13:12 +0000
@@ -7,8 +7,8 @@
 TriaxialTest(numberOfGrains=2000,noFiles=True).generate(loadFrom)
 O.load(loadFrom)
 
-collider=utils.typedEngine('InsertionSortCollider')
-newton=utils.typedEngine('NewtonIntegrator')
+collider=typedEngine('InsertionSortCollider')
+newton=typedEngine('NewtonIntegrator')
 
 # use striding; say "if 0:" to disable striding and compare to regular runs
 if 1:

=== modified file 'examples/test/collider-stride.py'
--- examples/test/collider-stride.py	2012-06-28 19:34:29 +0000
+++ examples/test/collider-stride.py	2013-03-28 11:13:12 +0000
@@ -5,11 +5,11 @@
 mat=O.materials.append(FrictMat(young=30e9,poisson=.2,density=4000,frictionAngle=.5))
 
 O.bodies.append([
-	utils.facet([[1,0,0],[-1,2,0],[-1,-2,0]],material=mat),
-	utils.sphere([0,0,2],.5,color=(0,1,0),material=mat)
+	facet([[1,0,0],[-1,2,0],[-1,-2,0]],material=mat),
+	sphere([0,0,2],.5,color=(0,1,0),material=mat)
 ])
 O.bodies[1].state.vel=Vector3(0,0,-1)
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 
 O.engines=[
 	ForceResetter(),

=== modified file 'examples/test/collider-sweep-simple.py'
--- examples/test/collider-sweep-simple.py	2012-06-28 19:34:29 +0000
+++ examples/test/collider-sweep-simple.py	2013-03-28 11:13:12 +0000
@@ -1,5 +1,5 @@
-O.bodies.append(utils.sphere([0,0,10],.5))
-#O.bodies.append(utils.sphere([0,0,0],.5,fixed=True))
+O.bodies.append(sphere([0,0,10],.5))
+#O.bodies.append(sphere([0,0,0],.5,fixed=True))
 
 O.engines=[
 	ForceResetter(),
@@ -12,7 +12,7 @@
 	NewtonIntegrator(damping=.1,gravity=[0,0,-1e4])
 ]
 collider.verletDist=.5
-O.dt=8e-2*utils.PWaveTimeStep()
+O.dt=8e-2*PWaveTimeStep()
 O.saveTmp()
 from yade import timing
 O.timingEnabled=True

=== added file 'examples/test/combined-kinematic-engine.py'
--- examples/test/combined-kinematic-engine.py	1970-01-01 00:00:00 +0000
+++ examples/test/combined-kinematic-engine.py	2012-12-03 07:58:30 +0000
@@ -0,0 +1,53 @@
+box = geom.facetBox(center=(0,0,0),extents=(1,2,3), color=(0,1,0))
+O.bodies.append(box)
+ids = [b.id for b in box]
+
+# set this parameter according to your computer power to make the simulation vizualization slower of faster
+coeff = 5.0
+
+nIterPerOneCycle = int(50000/coeff)
+vel = 10000*coeff
+angVel = 8000*coeff
+
+# function for changing motion, sets transEngine.translationAxis, rotEngine.angularVelocity and rotEngine.zeroPoint
+def updateKinematicEngines():
+	part = (O.iter / nIterPerOneCycle) % 4
+	if   part == 0: # fist part
+		v = Vector3(1,0,0)
+		av = 0
+	elif part == 1: # second part
+		v = Vector3(0,1,0)
+		av = angVel
+	elif part == 2: # third part
+		v = Vector3(-1,0,0)
+		av = -2*angVel
+	elif part == 3: # fourth part
+		v = Vector3(0,-1,0)
+		av = angVel
+	transEngine.translationAxis = v
+	rotEngine.angularVelocity = av
+	rotEngine.zeroPoint += v*vel*O.dt
+
+O.engines = [
+	ForceResetter(),
+	PyRunner(iterPeriod=1, command="updateKinematicEngines()" ),
+	# construct CombinedKinematicEngine with label, add (with +) TranslationEngine and RotationEngine
+	CombinedKinematicEngine(ids=ids,label='combEngine') + TranslationEngine(translationAxis=(1,0,0),velocity=vel) + RotationEngine(rotationAxis=(0,0,1), angularVelocity=0, rotateAroundZero=True, zeroPoint=(0,0,0)),
+	NewtonIntegrator(),
+]
+
+# get TranslationEngine and RotationEngine from CombinedKinematicEngine
+transEngine, rotEngine = combEngine.comb[0], combEngine.comb[1]
+print
+print 'transEngine:', transEngine
+print 'rotEngine:', rotEngine
+print
+
+
+try:
+	from yade import qt
+	qt.View()
+except:
+	print 'No graphics, sorry..'
+
+O.run()

=== modified file 'examples/test/energy.py'
--- examples/test/energy.py	2012-03-13 15:23:04 +0000
+++ examples/test/energy.py	2013-03-28 11:13:12 +0000
@@ -1,6 +1,6 @@
 from yade import pack,plot
 
-utils.readParamsFromTable(useL3Geom=True,nonviscDamp=0,frictAngle=0,useClumps=False,noTableOk=True)
+readParamsFromTable(useL3Geom=True,nonviscDamp=0,frictAngle=0,useClumps=False,noTableOk=True)
 from yade.params import table
 
 if 1:
@@ -10,8 +10,8 @@
 	# use clumps of 2 spheres instead, to have rotation without friction 
 	else: sp.makeClumpCloud((0,0,0),(1,1,1),[pack.SpherePack([((0,0,0),.05),((0,0,.08),.02)])],periodic=False)
 	sp.toSimulation()
-else: O.bodies.append(utils.sphere((0,0,2),radius=.5)) # one single bouncing ball
-O.bodies.append(utils.wall(position=0,axis=2,sense=1))
+else: O.bodies.append(sphere((0,0,2),radius=.5)) # one single bouncing ball
+O.bodies.append(wall(position=0,axis=2,sense=1))
 
 O.engines=[
 	ForceResetter(),
@@ -20,10 +20,10 @@
 	NewtonIntegrator(damping=table.nonviscDamp,kinSplit=True,gravity=(0,0,-9.81)),
 	PyRunner(iterPeriod=1,command='addPlotData()'),
 ]
-O.dt=.1*utils.PWaveTimeStep()
+O.dt=.1*PWaveTimeStep()
 
 def addPlotData():
-	Ek,maxId=utils.kineticEnergy(findMaxId=True)
+	Ek,maxId=kineticEnergy(findMaxId=True)
 	plot.addData(i=O.iter,total=O.energy.total(),maxId=maxId,**O.energy)
 
 # turn on energy tracking

=== modified file 'examples/test/exact-rot-facet.py'
--- examples/test/exact-rot-facet.py	2012-04-30 23:31:20 +0000
+++ examples/test/exact-rot-facet.py	2013-03-28 16:15:54 +0000
@@ -3,7 +3,6 @@
 ## TODO: verify that the code for facet & hasShear is physically correct!
 ##
 
-from math import *
 O.engines=[
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb(),Bo1_Facet_Aabb()]),
@@ -16,12 +15,12 @@
 	RotationEngine(ids=[1],rotationAxis=[1,0,0],angularVelocity=.01),
 	NewtonIntegrator(damping=0.2)
 ]
-from yade import utils
+
 scale=.1
-O.bodies.append(utils.facet([[scale,0,0],[-scale,-scale,0],[-scale,scale,0]],fixed=True,color=[1,0,0]))
-O.bodies.append(utils.sphere([0,0,.99*scale],1*scale,color=[0,1,0],wire=True,fixed=True))
+O.bodies.append(facet([[scale,0,0],[-scale,-scale,0],[-scale,scale,0]],fixed=True,color=[1,0,0]))
+O.bodies.append(sphere([0,0,.99*scale],1*scale,color=[0,1,0],wire=True,fixed=True))
 
-O.dt=.4*utils.PWaveTimeStep()
+O.dt=.4*PWaveTimeStep()
 from yade import qt
 qt.View()
 renderer=qt.Renderer()

=== modified file 'examples/test/exact-rot.py'
--- examples/test/exact-rot.py	2012-04-30 23:31:20 +0000
+++ examples/test/exact-rot.py	2013-03-28 16:15:54 +0000
@@ -1,5 +1,5 @@
 # -*- encoding=utf-8 -*-
-from math import *
+
 O.engines=[
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb()]),
@@ -13,11 +13,11 @@
 	RotationEngine(ids=[0],rotationAxis=(1,1,1),angularVelocity=-.02),
 	NewtonIntegrator(damping=.2,gravity=(0,0,-9.81))
 ]
-from yade import utils
-O.bodies.append(utils.sphere([0,0,0],1,fixed=True,color=[1,0,0],wire=True))
-O.bodies.append(utils.sphere([0,sqrt(2),sqrt(2)],1,color=[0,1,0],wire=True))
-
-O.dt=.01*utils.PWaveTimeStep()
+
+O.bodies.append(sphere([0,0,0],1,fixed=True,color=[1,0,0],wire=True))
+O.bodies.append(sphere([0,sqrt(2),sqrt(2)],1,color=[0,1,0],wire=True))
+
+O.dt=.01*PWaveTimeStep()
 O.saveTmp()
 #o.run(100000); o.wait(); print o.iter/o.realtime,'iterations/sec'
 from yade import qt

=== modified file 'examples/test/facet-sphere-ViscElBasic-peri.py'
--- examples/test/facet-sphere-ViscElBasic-peri.py	2012-03-13 15:23:04 +0000
+++ examples/test/facet-sphere-ViscElBasic-peri.py	2013-03-28 11:13:12 +0000
@@ -3,7 +3,7 @@
 # Testing facet-sphere interaction in periodic case.
 # Pass, if the sphere is rolling from left to right through the period.
 
-from yade import utils
+
 
 sphereRadius=0.1
 tc=0.001# collision time 
@@ -11,7 +11,7 @@
 es=0.3  # tangential restitution coefficient
 density=2700
 frictionAngle=radians(35)# 
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) 
 sphereMat=O.materials.append(ViscElMat(density=density,frictionAngle=frictionAngle,**params))
 
@@ -21,12 +21,12 @@
 for i in range(0,n):
 	for j in range(0,n):
 		O.bodies.append([
-			utils.facet( [(i*s,j*s,0.1),(i*s,(j+1)*s,0.1),((i+1)*s,(j+1)*s,0.1)],material=facetMat),
-			utils.facet( [(i*s,j*s,0.1),((i+1)*s,j*s,0.1),((i+1)*s,(j+1)*s,0.1)],material=facetMat),
+			facet( [(i*s,j*s,0.1),(i*s,(j+1)*s,0.1),((i+1)*s,(j+1)*s,0.1)],material=facetMat),
+			facet( [(i*s,j*s,0.1),((i+1)*s,j*s,0.1),((i+1)*s,(j+1)*s,0.1)],material=facetMat),
 		])
 
 # Spheres
-sphId=O.bodies.append([utils.sphere((0.5,0.5,0.2), 0.1, material=sphereMat)])
+sphId=O.bodies.append([sphere((0.5,0.5,0.2), 0.1, material=sphereMat)])
 O.bodies[sphId[-1]].state.vel=(0.5,0,0)
 
 ## Engines 

=== modified file 'examples/test/facet-sphere-ViscElBasic.py'
--- examples/test/facet-sphere-ViscElBasic.py	2012-03-13 15:23:04 +0000
+++ examples/test/facet-sphere-ViscElBasic.py	2013-03-28 11:13:12 +0000
@@ -11,15 +11,15 @@
 es = 0.3
 
 ## Import wall's geometry
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 facetMat=O.materials.append(ViscElMat(frictionAngle=frictionAngle,**params)) 
 sphereMat=O.materials.append(ViscElMat(density=Density,frictionAngle=frictionAngle,**params))
 
-facetId=O.bodies.append(utils.facet( [ (-1,0,0), (1,1,0), (1,-1,0)], material=facetMat,color=(1,0,0)))
+facetId=O.bodies.append(facet( [ (-1,0,0), (1,1,0), (1,-1,0)], material=facetMat,color=(1,0,0)))
 
 sphIds=O.bodies.append([
-	utils.sphere( (0,0,0.1),0.1, material=sphereMat,color=(0,1,0)), 
-	utils.sphere( (0.9,0,0.1),0.1, material=sphereMat,color=(0,1,0))
+	sphere( (0,0,0.1),0.1, material=sphereMat,color=(0,1,0)), 
+	sphere( (0.9,0,0.1),0.1, material=sphereMat,color=(0,1,0))
 	])
 
 O.bodies[sphIds[1]].state.blockedDOFs='XYZ'

=== modified file 'examples/test/facet-sphere.py'
--- examples/test/facet-sphere.py	2012-06-28 19:34:29 +0000
+++ examples/test/facet-sphere.py	2013-03-28 11:13:12 +0000
@@ -15,17 +15,17 @@
 	]
 
 O.bodies.append([
-	utils.facet([[-1,-1,0],[1,-1,0],[0,1,0]],fixed=True,color=[1,0,0]),
-	utils.facet([[1,-1,0],[0,1,0,],[1,.5,.5]],fixed=True)
+	facet([[-1,-1,0],[1,-1,0],[0,1,0]],fixed=True,color=[1,0,0]),
+	facet([[1,-1,0],[0,1,0,],[1,.5,.5]],fixed=True)
 ])
 
 import random
 for i in range(0,100):
-	s=utils.sphere([random.gauss(0,1),random.gauss(0,1),random.uniform(1,2)],random.uniform(.02,.05))
+	s=sphere([random.gauss(0,1),random.gauss(0,1),random.uniform(1,2)],random.uniform(.02,.05))
 	s.state.vel=Vector3(random.gauss(0,.1),random.gauss(0,.1),random.gauss(0,.1))
 	O.bodies.append(s)
 
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.run()
 O.saveTmp('init')
 

=== modified file 'examples/test/flat-collider.py'
--- examples/test/flat-collider.py	2012-06-28 19:34:29 +0000
+++ examples/test/flat-collider.py	2013-03-28 11:13:12 +0000
@@ -1,5 +1,5 @@
-from yade import utils,pack,timing
-#O.bodies.append([	utils.sphere((0.2,0,0),.5,fixed=True), utils.sphere((0.2,0.0,1.01),.5), ])
+from yade import pack,timing
+#O.bodies.append([	sphere((0.2,0,0),.5,fixed=True), sphere((0.2,0.0,1.01),.5), ])
 O.bodies.append(pack.regularHexa(pack.inAlignedBox((0,0,0),(10,10,1)),radius=.5,gap=0,fixed=True))
 O.bodies.append(pack.regularOrtho(pack.inAlignedBox((3,3,3),(7,7,4)),radius=.05,gap=0))
 O.engines=[
@@ -13,7 +13,7 @@
 	),
 	NewtonIntegrator(damping=0.4,gravity=[0,0,-10]),
 ]
-O.dt=.6*utils.PWaveTimeStep()
+O.dt=.6*PWaveTimeStep()
 O.saveTmp()
 #O.step()
 #while True:

=== modified file 'examples/test/force-move.py'
--- examples/test/force-move.py	2012-03-13 15:23:04 +0000
+++ examples/test/force-move.py	2013-03-28 11:13:12 +0000
@@ -1,4 +1,4 @@
-O.bodies.append(utils.sphere([0,0,0],1,fixed=False))
+O.bodies.append(sphere([0,0,0],1,fixed=False))
 O.engines=[
 	ForceResetter(),
 	PyRunner(command='O.forces.addMove(0,(1e-2,0,0))',iterPeriod=1),

=== modified file 'examples/test/force-network-video.py'
--- examples/test/force-network-video.py	2012-03-12 20:02:11 +0000
+++ examples/test/force-network-video.py	2013-03-28 11:13:12 +0000
@@ -1,6 +1,6 @@
 print 30*'*'+' WARNING '+30*'*'+'\nFor hardware/driver/...? reasons related to 3d, this script might\nsometimes crash when the first snapshot is taken with message such as\n\n\tQGLContext::makeCurrent(): Failed.\n\nor\n\n\tFatal IO error 11 (Resource temporarily unavailable) on X server :0.0.\n\nA workaround is to open the 3d view by hand, rather than having it\nopen by SnapshotEngine automatically when the first snapshot is\nabout to be taken. Sometimes only the message is displayed,\nwithout crash.\n'+25*'*'+' This is a known bug. '+25*'*'
 TriaxialTest(noFiles=True).load()
-from yade import qt,utils
+from yade import qt
 O.engines=O.engines+[
 	qt.SnapshotEngine(fileBase=O.tmpFilename(),label='snapshotter',iterPeriod=5,ignoreErrors=False),
 	PyRunner(iterPeriod=500,command='finito()')
@@ -16,7 +16,7 @@
 	For that reason, O.run() is at the end of the script and this function will be called
 	once we want to exit really.
 	"""
-	utils.makeVideo(snapshotter.snapshots,out='/tmp/video.avi')
+	makeVideo(snapshotter.snapshots,out='/tmp/video.avi')
 	print "Video saved in /tmp/video.avi"
 	import sys
 	sys.exit(0)

=== modified file 'examples/test/genCylLSM.py'
--- examples/test/genCylLSM.py	2012-03-12 20:02:11 +0000
+++ examples/test/genCylLSM.py	2013-03-28 16:15:54 +0000
@@ -14,8 +14,6 @@
 https://svn.esscc.uq.edu.au/svn/esys3/lsm/contrib/LSMGenGeo/
 """
 from yade import pack,ymport
-from yade import utils
-from math import *
 
 try:
 	from GenGeo import *

=== modified file 'examples/test/helix.py'
--- examples/test/helix.py	2012-03-13 15:23:04 +0000
+++ examples/test/helix.py	2013-03-28 11:13:12 +0000
@@ -1,5 +1,5 @@
 # script for testing InterpolatingHelixEngine: sphere going in a sphere-like motion around bar
-O.bodies.append([utils.box([0,0,0],[.005,.005,1],fixed=True),utils.sphere([0,.1,-1],.04,fixed=False)])
+O.bodies.append([box([0,0,0],[.005,.005,1],fixed=True),sphere([0,.1,-1],.04,fixed=False)])
 O.engines=[
 	InterpolatingHelixEngine(ids=[1],times=[10,20,30,40,50,60,70,80,90,100],angularVelocities=[1,2,3,4,5,3,1,-1,-3,0],rotationAxis=[0,0,1],zeroPoint=[0,0,0], wrap=True,slope=.003,label='spiral'),
 ]

=== modified file 'examples/test/interpolating-force.py'
--- examples/test/interpolating-force.py	2012-03-13 15:23:04 +0000
+++ examples/test/interpolating-force.py	2013-03-28 11:13:12 +0000
@@ -36,12 +36,12 @@
 ]
 
 O.bodies.append([
-	utils.sphere([0,0,0],1,fixed=True,color=[1,0,0]),
-	utils.sphere([0,0,2],1,color=[0,1,0])
+	sphere([0,0,0],1,fixed=True,color=[1,0,0]),
+	sphere([0,0,2],1,color=[0,1,0])
 ])
 
 # elastic timestep
-O.dt=.5*utils.PWaveTimeStep()
+O.dt=.5*PWaveTimeStep()
 
 # callback for plotDataCollector
 import yade.plot as yp

=== modified file 'examples/test/kinematic.py'
--- examples/test/kinematic.py	2012-03-13 15:23:04 +0000
+++ examples/test/kinematic.py	2013-03-28 11:13:12 +0000
@@ -3,8 +3,8 @@
 # The second engine does the same on body #1 as the first one does on #0 (the local rotation is not present)
 
 O.bodies.append([
-	utils.sphere((-1,0,0),.3,color=(1,0,.5),fixed=False,wire=True),
-	utils.sphere((1,0,0),.3,color=(0,1,0),fixed=False,wire=True)
+	sphere((-1,0,0),.3,color=(1,0,.5),fixed=False,wire=True),
+	sphere((1,0,0),.3,color=(0,1,0),fixed=False,wire=True)
 ])
 
 O.engines=[

=== modified file 'examples/test/mindlin.py'
--- examples/test/mindlin.py	2012-03-13 15:23:04 +0000
+++ examples/test/mindlin.py	2013-03-28 16:15:54 +0000
@@ -26,14 +26,14 @@
 O.materials.append(mat)
 
 ## create two spheres (one will be fixed) and append them
-from yade import utils
-s0=utils.sphere([0,0,0],1,color=[0,1,0],fixed=False,wire=True,material='Friction')
-s1=utils.sphere([2,0,0],1,color=[0,2,0],fixed=True,wire=True,material='Friction')
+
+s0=sphere([0,0,0],1,color=[0,1,0],fixed=False,wire=True,material='Friction')
+s1=sphere([2,0,0],1,color=[0,2,0],fixed=True,wire=True,material='Friction')
 O.bodies.append(s0)
 O.bodies.append(s1)
 
 ## time step
-O.dt=.2*utils.PWaveTimeStep()
+O.dt=.2*PWaveTimeStep()
 O.saveTmp('Mindlin')
 
 from yade import qt
@@ -44,7 +44,6 @@
 ##### now the part pertaining to plots #####
 ############################################
 
-from math import *
 from yade import plot
 ## make one plot: step as function of fn
 plot.plots={'un':('fn')}

=== modified file 'examples/test/multi/multi.py'
--- examples/test/multi/multi.py	2012-03-12 20:02:11 +0000
+++ examples/test/multi/multi.py	2013-03-28 11:16:41 +0000
@@ -2,8 +2,8 @@
 # https://yade-dem.org/wiki/ScriptParametricStudy
 #
 ## read parameters from table here
-from yade import utils, plot
-utils.readParamsFromTable(gravity=-9.81,density=2400,initialSpeed=10,noTableOk=True)
+from yade import  plot
+readParamsFromTable(gravity=-9.81,density=2400,initialSpeed=10,noTableOk=True)
 from yade.params.table import *
 print gravity,density,initialSpeed
 
@@ -21,13 +21,13 @@
 	NewtonIntegrator(damping=0.4,gravity=(0,0,gravity))## here we use the 'gravity' parameter
 ]
 O.bodies.append([
-	utils.box([0,50,0],extents=[1,50,1],fixed=True,color=[1,0,0]),
-	utils.sphere([0,0,10],1,color=[0,1,0])
+	box([0,50,0],extents=[1,50,1],fixed=True,color=[1,0,0]),
+	sphere([0,0,10],1,color=[0,1,0])
 ])
 
 O.bodies[1].state.vel=(0,initialSpeed,0) ## assign initial velocity
 
-O.dt=.8*utils.PWaveTimeStep()
+O.dt=.8*PWaveTimeStep()
 ## o.saveTmp('initial')
 def myAddPlotData():
 	s=O.bodies[1]

=== modified file 'examples/test/pack-cloud.py'
--- examples/test/pack-cloud.py	2012-03-13 15:23:04 +0000
+++ examples/test/pack-cloud.py	2013-03-28 11:13:12 +0000
@@ -4,7 +4,7 @@
 O.cellSize=Vector3(10,10,10)
 print p.makeCloud(Vector3(0,0,0),Vector3(10,10,10),.5,.5,200,True)
 for s in p:
-	O.bodies.append(utils.sphere(s[0],s[1]))
+	O.bodies.append(sphere(s[0],s[1]))
 O.engines=[BoundDispatcher([Bo1_Sphere_Aabb()])]
 from yade import qt
 qt.View()

=== modified file 'examples/test/performance/checkPerf.py'
--- examples/test/performance/checkPerf.py	2012-03-13 09:51:32 +0000
+++ examples/test/performance/checkPerf.py	2013-03-28 11:16:16 +0000
@@ -1,6 +1,6 @@
 # -*- coding: utf-8
 
-from yade import utils,pack,export,geom,timing,bodiesHandling
+from yade import pack,export,geom,timing,bodiesHandling
 import time,numpy
 	
 radRAD=[23.658,				#5000 elements
@@ -44,7 +44,7 @@
 		frictionAngle=radians(35)
 		density=2300
 		
-		params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+		params=getViscoelasticFromSpheresInteraction(tc,en,es)
 		defMat=O.materials.append(ViscElMat(density=density,frictionAngle=frictionAngle,**params)) # **params sets kn, cn, ks, cs
 		
 		O.dt=.1*tc # time step
@@ -61,7 +61,7 @@
 		floorId+=O.bodies.append(geom.facetBox(geometryParameters['center'],geometryParameters['extends']/2.0*1.05,material=defMat)) #Floor
 		
 		#Calculate the mass of spheres
-		sphMass = utils.getSpheresVolume()*density
+		sphMass = getSpheresVolume()*density
 		
 		# Create engines
 		O.engines=[
@@ -76,7 +76,10 @@
 		]
 		
 		print "number of bodies %d"%len(O.bodies)
+		# Initialize the collider else it is not possible to compare the results with different nbIter
+		O.run(1,1)
 		O.timingEnabled=True
+		timing.reset()
 		tStart=time.time()
 		
 		O.run(nbIter)

=== modified file 'examples/test/peri3dController_example1.py'
--- examples/test/peri3dController_example1.py	2012-08-05 15:55:46 +0000
+++ examples/test/peri3dController_example1.py	2013-03-28 11:13:12 +0000
@@ -4,7 +4,7 @@
 from yade import pack, plot
 
 # create some material
-O.materials.append(CpmMat(young=25e9,frictionAngle=.7,poisson=.2,sigmaT=3e6,epsCrackOnset=1e-4,crackOpening=5e-6))
+O.materials.append(CpmMat(neverDamage=True,young=25e9,frictionAngle=.7,poisson=.2,sigmaT=3e6,epsCrackOnset=1e-4,relDuctility=30))
 
 # create periodic assembly of particles
 initSize=1.2
@@ -26,16 +26,18 @@
 # in how many time steps should be the goal state reached
 nSteps=4000
 
-O.dt=utils.PWaveTimeStep()/2
+O.dt=PWaveTimeStep()/2
 EnlargeFactor=1.5
+EnlargeFactor=1.0
 O.engines=[
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb(aabbEnlargeFactor=EnlargeFactor,label='bo1s')]),
 	InteractionLoop(
-		[Ig2_Sphere_Sphere_Dem3DofGeom(distFactor=EnlargeFactor,label='ig2ss')],
-		[Ip2_CpmMat_CpmMat_CpmPhys()],[Law2_Dem3DofGeom_CpmPhys_Cpm()]),
+		[Ig2_Sphere_Sphere_ScGeom(interactionDetectionFactor=EnlargeFactor,label='ig2ss')],
+		[Ip2_CpmMat_CpmMat_CpmPhys()],[Law2_ScGeom_CpmPhys_Cpm()]),
 	NewtonIntegrator(),
-	Peri3dController(	goal=(10e-4,-3e-4,0, -5e6,3e-4,2e6), # Vector6 of prescribed final values
+	Peri3dController(
+							goal=(20e-4,-6e-4,0, -2e6,3e-4,2e6), # Vector6 of prescribed final values (xx,yy,zz, yz,zx,xy)
 							stressMask=0b101100,    # prescribed ex,ey,sz,syz,ezx,sxy;   e..strain;  s..stress
 							nSteps=nSteps, 			# how many time steps the simulation will last
 							# after reaching nSteps do doneHook action
@@ -59,7 +61,7 @@
 ]
 
 O.step()
-#bo1s.aabbEnlargeFactor=ig2ss.distFactor=-1
+bo1s.aabbEnlargeFactor=ig2ss.interactionDetectionFactor=1.
 
 O.run(); #O.wait()
 plot.plot(subPlots=False)

=== modified file 'examples/test/peri3dController_shear.py'
--- examples/test/peri3dController_shear.py	2012-08-05 15:55:46 +0000
+++ examples/test/peri3dController_shear.py	2013-04-24 19:49:00 +0000
@@ -8,7 +8,7 @@
 from yade import pack,plot,qt
 
 # define material
-O.materials.append(CpmMat(young=25e9,poisson=.2,sigmaT=3e6,epsCrackOnset=1e-4,crackOpening=1e-6))
+O.materials.append(CpmMat(young=25e9,poisson=.2,sigmaT=3e6,epsCrackOnset=1e-4,relDuctility=1e-6))
 
 # create periodic assembly of particles
 initSize=1.2
@@ -30,7 +30,7 @@
 		eyz=p3d.strain[3],ezx=p3d.strain[4],exy=p3d.strain[5],
 	)
 
-O.dt=utils.PWaveTimeStep()/2
+O.dt=PWaveTimeStep()/2
 
 # define the first part of simulation, hydrostatic compression
 enlargeFactor=1.5
@@ -38,8 +38,8 @@
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb(aabbEnlargeFactor=enlargeFactor,label='bo1s')]),
 	InteractionLoop(
-		[Ig2_Sphere_Sphere_Dem3DofGeom(distFactor=enlargeFactor,label='ig2ss')],
-		[Ip2_CpmMat_CpmMat_CpmPhys()],[Law2_Dem3DofGeom_CpmPhys_Cpm()]),
+		[Ig2_Sphere_Sphere_ScGeom(interactionDetectionFactor=enlargeFactor,label='ig2ss')],
+		[Ip2_CpmMat_CpmMat_CpmPhys()],[Law2_ScGeom_CpmPhys_Cpm()]),
 	NewtonIntegrator(),
 	Peri3dController(	goal=(0,0,0, 0,0,5e-3), # Vector6 of prescribed final values
 							stressMask=0b011111,
@@ -51,7 +51,7 @@
 	PyRunner(command='plotAddData()',iterPeriod=1),
 ]
 O.step()
-#bo1s.aabbEnlargeFactor=ig2ss.distFactor=-1
+bo1s.aabbEnlargeFactor=ig2ss.interactionDetectionFactor=1.0
 
 renderer=qt.Renderer()
 renderer.intrPhys,renderer.shape=True,False

=== modified file 'examples/test/peri3dController_triaxialCompression.py'
--- examples/test/peri3dController_triaxialCompression.py	2012-06-28 19:34:29 +0000
+++ examples/test/peri3dController_triaxialCompression.py	2013-04-24 19:49:00 +0000
@@ -8,8 +8,6 @@
 # in this case there is almost no difference, but in script peri3dController_shear,
 # the cell rotation has significant effect)
 
-#FIXME: Law2_Dem3DofGeom_FrictPhys_CundallStrack replaced by Law2_ScGeom_FrictPhys_CundallStrack because the first is removed, but Peri3DEngine is broken by this change due to sign inversion in stress. A 'useDem3dof' flag like in PeriTriaxController is needed.
-
 from yade import pack,plot,qt
 
 # define material
@@ -34,7 +32,7 @@
 		eyz=p3d.strain[3],ezx=p3d.strain[4],exy=p3d.strain[5],
 	)
 
-O.dt=utils.PWaveTimeStep()/2
+O.dt=PWaveTimeStep()/2
 
 # define the first part of simulation, hydrostatic compression
 O.engines=[

=== removed file 'examples/test/peri8.py'
--- examples/test/peri8.py	2012-03-12 20:02:11 +0000
+++ examples/test/peri8.py	1970-01-01 00:00:00 +0000
@@ -1,9 +0,0 @@
-a=1.; r=a/4.
-O.bodies.append(
-	[utils.sphere(c,r) for c in [(r,r,r),(3*r,r,r),(3*r,3*r,r),(r,3*r,r),(r,r,3*r),(3*r,r,3*r),(3*r,3*r,3*r),(r,3*r,3*r)]]
-)
-O.periodic=True
-O.cell.refSize=(a,a,a)
-zRot=-pi/4.
-O.cell.trsf=Matrix3(cos(zRot),-sin(zRot),0,sin(zRot),cos(zRot),0,0,0,1)
-p7=O.bodies[7].state.pos

=== modified file 'examples/test/periodic-geom-compare.py'
--- examples/test/periodic-geom-compare.py	2012-06-28 19:34:29 +0000
+++ examples/test/periodic-geom-compare.py	2013-03-28 11:13:12 +0000
@@ -13,7 +13,7 @@
 sp.toSimulation()
 
 # specify which family of geometry functors to use
-utils.readParamsFromTable(noTableOk=True,geom='sc')
+readParamsFromTable(noTableOk=True,geom='sc')
 from yade.params.table import geom
 
 if geom=='sc':
@@ -31,7 +31,7 @@
 	loop,
 	NewtonIntegrator(damping=.6),
 ]
-O.dt=0.5*utils.PWaveTimeStep()
+O.dt=0.5*PWaveTimeStep()
 try:
 	from yade import qt
 	qt.View()
@@ -42,7 +42,7 @@
 #O.run(10000,True);
 #rrr=qt.Renderer(); rrr.intrAllWire,rrr.intrGeom=True,False
 
-if utils.runningInBatch():
+if runningInBatch():
 	O.timingEnabled=True
 	O.run(300000,True)
 	O.timingEnabled

=== modified file 'examples/test/periodic-shear.py'
--- examples/test/periodic-shear.py	2012-06-28 19:34:29 +0000
+++ examples/test/periodic-shear.py	2013-03-28 19:23:34 +0000
@@ -1,9 +1,9 @@
 O.periodic=True
 O.cell.setBox(.55,.55,.55)
-O.bodies.append(utils.facet([[.4,.0001,.3],[.2,.0001,.3],[.3,.2,.2]]))
-O.bodies.append(utils.sphere([.3,.1,.4],.05,fixed=False))
-O.bodies.append(utils.sphere([.200001,.2000001,.4],.05,fixed=True))
-O.bodies.append(utils.sphere([.3,0,0],.1,fixed=True))
+O.bodies.append(facet([[.4,.0001,.3],[.2,.0001,.3],[.3,.2,.2]]))
+O.bodies.append(sphere([.3,.1,.4],.05,fixed=False))
+O.bodies.append(sphere([.200001,.2000001,.4],.05,fixed=True))
+O.bodies.append(sphere([.3,0,0],.1,fixed=True))
 O.engines=[
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()],label='isc'),
@@ -18,7 +18,7 @@
 
 def doCellFlip():
 	flip=1 if O.cell.trsf[1,2]<0 else -1;
-	utils.flipCell(Matrix3(0,0,0, 0,0,flip, 0,0,0))
+	flipCell(Matrix3(0,0,0, 0,0,flip, 0,0,0))
 
 #g=0.
 #while False:
@@ -26,14 +26,13 @@
 #	time.sleep(0.001)
 #	g+=1e-3
 O.cell.trsf=Matrix3(1,0,0, 0,1,.5, 0,0,1)
-O.dt=2e-2*utils.PWaveTimeStep()
+O.dt=2e-2*PWaveTimeStep()
 O.step()
 O.saveTmp()
 rrr=yade.qt.Renderer()
 rrr.intrAllWire,rrr.bound=True,True
 #isc.watch1,isc.watch2=0,-1
 
-#from yade import log
 #import yade.qt,time
 #v=yade.qt.View()
 #v.axes=True

=== modified file 'examples/test/periodic-simple-shear.py'
--- examples/test/periodic-simple-shear.py	2012-04-13 18:11:34 +0000
+++ examples/test/periodic-simple-shear.py	2013-03-28 11:13:12 +0000
@@ -11,7 +11,7 @@
 sp=pack.SpherePack()
 radius=5e-3
 num=sp.makeCloud((0,0,0),(.1,.1,.1),radius,.2,500,periodic=True) # min,max,radius,rRelFuzz,spheresInCell,periodic
-O.bodies.append([utils.sphere(s[0],s[1]) for s in sp])
+O.bodies.append([sphere(s[0],s[1]) for s in sp])
 
 
 O.engines=[
@@ -41,7 +41,7 @@
 		#print 'Done, pausing now.'
 		#O.pause()
 		
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.run(7000);
 qt.View()
 #r=qt.Renderer()

=== modified file 'examples/test/periodic-simple.py'
--- examples/test/periodic-simple.py	2012-06-28 19:34:29 +0000
+++ examples/test/periodic-simple.py	2013-03-28 11:13:12 +0000
@@ -16,16 +16,16 @@
 	TranslationEngine(translationAxis=(1,0,0),velocity=10,ids=[0]),
 	NewtonIntegrator(damping=.4,gravity=[0,0,-10])
 ]
-O.bodies.append(utils.sphere([-4,0,11],2,fixed=True))
-O.bodies.append(utils.sphere([0,-2,5.5],2))
-O.bodies.append(utils.sphere([0,2,5.5],2))
-O.bodies.appendClumped([utils.sphere([0,4,8],.8),utils.sphere([0,5,7],.6)])
+O.bodies.append(sphere([-4,0,11],2,fixed=True))
+O.bodies.append(sphere([0,-2,5.5],2))
+O.bodies.append(sphere([0,2,5.5],2))
+O.bodies.appendClumped([sphere([0,4,8],.8),sphere([0,5,7],.6)])
 # sets up the periodic cell
 O.periodic=True
 O.cell.setBox(10,10,10)
 # normally handled in by the simulation... but we want to have the rendering right before start
 #O.cell.postProcessAttributes()
-O.dt=.1*utils.PWaveTimeStep()
+O.dt=.1*PWaveTimeStep()
 O.saveTmp()
 from yade import qt
 qt.Controller()

=== modified file 'examples/test/periodic-triax-settingHsize.py'
--- examples/test/periodic-triax-settingHsize.py	2012-04-13 17:49:03 +0000
+++ examples/test/periodic-triax-settingHsize.py	2013-03-28 11:13:12 +0000
@@ -10,7 +10,7 @@
 		    0.3, -0.3, 1.0)
 sp=pack.SpherePack()
 num=sp.makeCloud(hSize=O.cell.hSize, rMean=-0.01,rRelFuzz=.2, num=500,periodic=True, porosity=0.52,distributeMass=False)
-O.bodies.append([utils.sphere(s[0],s[1]) for s in sp])
+O.bodies.append([sphere(s[0],s[1]) for s in sp])
 
 
 O.engines=[
@@ -26,7 +26,7 @@
 	NewtonIntegrator(damping=.2),
 	#PyRunner(iterPeriod=500,command='print "strain: ",triax.strain," stress: ",triax.stress')
 ]
-O.dt=0.5*utils.PWaveTimeStep()
+O.dt=0.5*PWaveTimeStep()
 qt.View()
 
 phase=0

=== modified file 'examples/test/periodic-triax.py'
--- examples/test/periodic-triax.py	2012-04-13 18:11:34 +0000
+++ examples/test/periodic-triax.py	2013-03-28 11:13:12 +0000
@@ -12,7 +12,7 @@
 sp=pack.SpherePack()
 radius=5e-3
 num=sp.makeCloud(Vector3().Zero,O.cell.refSize,radius,.2,500,periodic=True) # min,max,radius,rRelFuzz,spheresInCell,periodic
-O.bodies.append([utils.sphere(s[0],s[1]) for s in sp])
+O.bodies.append([sphere(s[0],s[1]) for s in sp])
 
 
 O.engines=[
@@ -28,7 +28,7 @@
 	PeriTriaxController(dynCell=True,mass=0.2,maxUnbalanced=0.01,relStressTol=0.02,goal=(-1e4,-1e4,0),stressMask=3,globUpdate=5,maxStrainRate=(1.,1.,1.),doneHook='triaxDone()',label='triax'),
 	NewtonIntegrator(damping=.2),
 ]
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.run();
 qt.View()
 

=== modified file 'examples/test/qt4-pyqglviewer.py'
--- examples/test/qt4-pyqglviewer.py	2012-03-12 20:02:11 +0000
+++ examples/test/qt4-pyqglviewer.py	2013-03-28 11:13:12 +0000
@@ -11,7 +11,7 @@
 	def draw(self):
 		self.renderer.render()
 
-O.bodies.append([utils.sphere((0,0,-.4),.3),utils.sphere((0,0,.4),.3)])
+O.bodies.append([sphere((0,0,-.4),.3),sphere((0,0,.4),.3)])
 
 viewer=Viewer()
 viewer.setWindowTitle('Yade')

=== modified file 'examples/test/remove-body.py'
--- examples/test/remove-body.py	2012-06-28 19:34:29 +0000
+++ examples/test/remove-body.py	2013-03-28 11:13:12 +0000
@@ -17,8 +17,8 @@
 	NewtonIntegrator(damping=0.01,gravity=[0,0,-10]),
 	]
 O.bodies.append([
-	utils.facet([[-1,-1,0],[1,-1,0],[0,1,0]],fixed=True,color=[1,0,0]),
-	utils.facet([[1,-1,0],[0,1,0,],[1,.5,.5]],fixed=True)
+	facet([[-1,-1,0],[1,-1,0],[0,1,0]],fixed=True,color=[1,0,0]),
+	facet([[1,-1,0],[0,1,0,],[1,.5,.5]],fixed=True)
 ])
 
 #Gl1_Facet(normals=True)
@@ -26,7 +26,7 @@
 import random,sys
 
 def addRandomSphere():
-	return O.bodies.append(utils.sphere([random.gauss(0,1),random.gauss(0,1),random.uniform(1,2)],random.uniform(.02,.05)))
+	return O.bodies.append(sphere([random.gauss(0,1),random.gauss(0,1),random.uniform(1,2)],random.uniform(.02,.05)))
 	O.bodies[len(O.bodies)-1].state.vel=[random.gauss(0,.1),random.gauss(0,.1),random.gauss(0,.1)]
 
 for i in range(0,100): addRandomSphere()

=== modified file 'examples/test/shear.py'
--- examples/test/shear.py	2012-03-13 15:23:04 +0000
+++ examples/test/shear.py	2013-03-28 11:13:12 +0000
@@ -4,8 +4,8 @@
 #
 
 O.bodies.append([
-	utils.sphere([0,0,0],.5000001,fixed=True,color=(1,0,0)),
-	utils.sphere([0,0,1],.5000001,fixed=False,color=(0,0,1))
+	sphere([0,0,0],.5000001,fixed=True,color=(1,0,0)),
+	sphere([0,0,1],.5000001,fixed=False,color=(0,0,1))
 ])
 O.engines=[
 	ForceResetter(),

=== modified file 'examples/test/sphere-sphere-ViscElBasic-peri.py'
--- examples/test/sphere-sphere-ViscElBasic-peri.py	2012-03-13 15:23:04 +0000
+++ examples/test/sphere-sphere-ViscElBasic-peri.py	2013-03-28 11:13:12 +0000
@@ -3,7 +3,7 @@
 # Testing sphere-sphere interaction in periodic case.
 # Pass, if the spheres moves along the X axis, interacting through the period.
 
-from yade import utils
+
 
 sphereRadius=0.1
 tc=0.001# collision time 
@@ -11,14 +11,14 @@
 es=1  # tangential restitution coefficient
 density=2700
 frictionAngle=radians(35)# 
-params=utils.getViscoelasticFromSpheresInteraction(tc,en,es)
+params=getViscoelasticFromSpheresInteraction(tc,en,es)
 sphereMat=O.materials.append(ViscElMat(density=density,frictionAngle=frictionAngle,**params))
 
 
 # Spheres
 sphId=O.bodies.append([
-	utils.sphere( (0.4,0.5,0.5), 0.1, material=sphereMat),
-	utils.sphere( (0.6,0.5,0.5), 0.1, material=sphereMat)
+	sphere( (0.4,0.5,0.5), 0.1, material=sphereMat),
+	sphere( (0.6,0.5,0.5), 0.1, material=sphereMat)
 	])
 O.bodies[sphId[-1]].state.vel=(0.5,0,0)
 O.bodies[sphId[0]].state.vel=(-0.5,0,0)

=== modified file 'examples/test/spheresFactory.py'
--- examples/test/spheresFactory.py	2012-03-13 15:23:04 +0000
+++ examples/test/spheresFactory.py	2013-03-28 11:13:12 +0000
@@ -1,5 +1,5 @@
 
-from yade import geom,utils,log
+from yade import geom,log
 
 shotsId,steelId=O.materials.append([
 	FrictMat(young=50e9,density=6000,poisson=.2,label='shots'),
@@ -36,8 +36,8 @@
 	PyRunner(iterPeriod=10000,command='if factory.numParticles>=factory.maxParticles: O.stopAtIter=O.iter+8000; timing.stats()')
 ]
 # the timestep must be smaller because of high linear velocities of particles
-# we cannot use utils.PWaveTimeStep directly, since there are no spheres generated yet
-O.dt=utils.SpherePWaveTimeStep(factory.rMin,O.materials[factory.materialId].density,O.materials[factory.materialId].young)
+# we cannot use PWaveTimeStep directly, since there are no spheres generated yet
+O.dt=SpherePWaveTimeStep(factory.rMin,O.materials[factory.materialId].density,O.materials[factory.materialId].young)
 O.saveTmp()
 #O.timingEnabled=True
 from yade import timing

=== modified file 'examples/test/subdomain-balancer.py'
--- examples/test/subdomain-balancer.py	2012-04-13 16:27:00 +0000
+++ examples/test/subdomain-balancer.py	2013-03-28 11:13:12 +0000
@@ -1,14 +1,14 @@
-from yade import pack,timing,utils
-utils.readParamsFromTable(noTableOk=True,num=12000)
+from yade import pack,timing
+readParamsFromTable(noTableOk=True,num=12000)
 import yade.params.table
 sp=pack.SpherePack()
 sp.makeCloud((0,0,0),(1,1,1),.03*((12000./yade.params.table.num)**(1/3.)),.5)
 sp.toSimulation()
-O.bodies.append(utils.wall((0,0,0),axis=2))
-O.bodies.append(utils.wall((0,0,0),axis=1))
-#O.bodies.append(utils.wall((0,0,0),axis=0))
-#O.bodies.append(utils.wall((0,2,0),axis=1))
-#O.bodies.append(utils.wall((2,0,0),axis=0))
+O.bodies.append(wall((0,0,0),axis=2))
+O.bodies.append(wall((0,0,0),axis=1))
+#O.bodies.append(wall((0,0,0),axis=0))
+#O.bodies.append(wall((0,2,0),axis=1))
+#O.bodies.append(wall((2,0,0),axis=0))
 O.engines=([SubdomainBalancer(axesOrder='xyz',colorize=True)] if 'SubdomainBalancer' in dir() else [])+[
 	ForceResetter(),
 	InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Wall_Aabb()],verletDist=.05*.05),
@@ -16,7 +16,7 @@
 	NewtonIntegrator(gravity=(0,0,-10)),
 	#PyRunner(iterPeriod=5000,command='O.pause(); timing.stats();')
 ]
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.timingEnabled=True
 #O.step(); #O.run(10000,True)
 timing.stats()

=== modified file 'examples/test/test-sphere-facet-corner.py'
--- examples/test/test-sphere-facet-corner.py	2012-06-28 19:34:29 +0000
+++ examples/test/test-sphere-facet-corner.py	2013-03-28 11:13:12 +0000
@@ -1,6 +1,6 @@
 # -*- encoding=utf-8 -*-
 
-from yade import utils
+
 
 ## PhysicalParameters 
 Young = 7e6
@@ -11,9 +11,9 @@
 mat=O.materials.append(FrictMat(young=Young,poisson=Poisson,density=Density,frictionAngle=26))
 
 O.bodies.append([
-        utils.sphere([0,0,0.6],0.25,material=mat),
-        utils.facet([[-0.707,-0.707,0.1],[0,1.414,0],[1.414,0,0]],dynamic=False,color=[1,0,0],material=mat),
-        utils.facet([[0,1.414,0],[1.414,0,0],[0.707,0.707,-2.0]],dynamic=False,color=[1,0,0],material=mat)])
+        sphere([0,0,0.6],0.25,material=mat),
+        facet([[-0.707,-0.707,0.1],[0,1.414,0],[1.414,0,0]],dynamic=False,color=[1,0,0],material=mat),
+        facet([[0,1.414,0],[1.414,0,0],[0.707,0.707,-2.0]],dynamic=False,color=[1,0,0],material=mat)])
 
 ## Engines 
 O.engines=[

=== modified file 'examples/test/test-sphere-facet.py'
--- examples/test/test-sphere-facet.py	2012-06-28 19:34:29 +0000
+++ examples/test/test-sphere-facet.py	2013-03-28 11:13:12 +0000
@@ -37,8 +37,8 @@
 	PyRunner(iterPeriod=4000,command='setGravity()'),
 	]
 O.bodies.append([
-	utils.facet([[-1,-1,0],[1,-1,0],[0,1,0]],fixed=True,color=[1,0,0],material=mat),
-	utils.sphere([0,0,sign*.49999],radius=.5,wire=True,material=mat),
+	facet([[-1,-1,0],[1,-1,0],[0,1,0]],fixed=True,color=[1,0,0],material=mat),
+	sphere([0,0,sign*.49999],radius=.5,wire=True,material=mat),
 ])
 O.timingEnabled=True
 O.saveTmp()

=== modified file 'examples/test/test_Ip2_FrictMat_CpmMat_FrictPhys.py'
--- examples/test/test_Ip2_FrictMat_CpmMat_FrictPhys.py	2012-08-05 20:02:34 +0000
+++ examples/test/test_Ip2_FrictMat_CpmMat_FrictPhys.py	2013-04-24 19:49:00 +0000
@@ -10,19 +10,18 @@
 density=4800 ## 4800  # twice the density, since porosity is about .5 (.62)
 epsCrackOnset=1e-4
 relDuctility=300
-#crackOpening=.15e-3*1e-4*30*100
 intRadius=1.5
 
 concMat  = O.materials.append(CpmMat(young=young,poisson=poisson,density=4800,sigmaT=3e6,relDuctility=30,epsCrackOnset=1e-4,neverDamage=False))
 frictMat = O.materials.append(FrictMat(young=young,poisson=poisson,density=4800))
 
-b1 = utils.sphere((0,0,0),1,material=concMat)
+b1 = sphere((0,0,0),1,material=concMat)
 b1.state.vel = Vector3(1,0,0)
-b2 = utils.sphere((0,5,0),1,material=concMat)
+b2 = sphere((0,5,0),1,material=concMat)
 b2.state.vel = Vector3(2,-2,0)
-b3 = utils.sphere((0,-4,0),1,material=frictMat)
+b3 = sphere((0,-4,0),1,material=frictMat)
 b3.state.vel = Vector3(1,3,0)
-b4 = utils.facet(((2,-5,-5),(2,-5,10),(2,10,-5)),material=frictMat)
+b4 = facet(((2,-5,-5),(2,-5,10),(2,10,-5)),material=frictMat)
 
 O.bodies.append((b1,b2,b3,b4))
 

=== modified file 'examples/test/triax-basic.py'
--- examples/test/triax-basic.py	2012-09-19 16:26:06 +0000
+++ examples/test/triax-basic.py	2013-03-28 11:13:12 +0000
@@ -16,9 +16,9 @@
 
 ## copy spheres from the packing into the scene
 ## use default material, don't care about that for now
-O.bodies.append([utils.sphere(center,rad,material='spheres') for center,rad in sp])
+O.bodies.append([sphere(center,rad,material='spheres') for center,rad in sp])
 ## create walls around the packing
-walls=utils.aabbWalls(thickness=1e-10,material='frictionless')
+walls=aabbWalls(thickness=1e-10,material='frictionless')
 wallIds=O.bodies.append(walls)
 
 triax=TriaxialCompressionEngine(

=== modified file 'examples/test/triax-cohesive.py'
--- examples/test/triax-cohesive.py	2012-09-21 11:40:55 +0000
+++ examples/test/triax-cohesive.py	2013-03-28 11:13:12 +0000
@@ -17,9 +17,9 @@
 
 
 ## copy spheres from the packing into the scene
-O.bodies.append([utils.sphere(center,rad,material='spheres') for center,rad in sp])
+O.bodies.append([sphere(center,rad,material='spheres') for center,rad in sp])
 ## create walls around the packing
-walls=utils.aabbWalls(material='frictionlessWalls')
+walls=aabbWalls(material='frictionlessWalls')
 wallIds=O.bodies.append(walls)
 
 triax=TriaxialCompressionEngine(

=== modified file 'examples/test/vtk-exporter/vtkExporter.py'
--- examples/test/vtk-exporter/vtkExporter.py	2012-03-13 15:23:04 +0000
+++ examples/test/vtk-exporter/vtkExporter.py	2013-03-28 11:14:53 +0000
@@ -1,12 +1,12 @@
 from yade import *
-from yade import utils,export
+from yade import export
 
 O.bodies.append([
-	utils.sphere((0,0,0),1),
-	utils.sphere((0,2,0),1),
-	utils.sphere((0,2,3),2),
-	utils.facet([Vector3(0,-3,-1),Vector3(0,-2,5),Vector3(5,4,0)]),
-	utils.facet([Vector3(0,-3,-1),Vector3(0,-2,5),Vector3(-5,4,0)])
+	sphere((0,0,0),1),
+	sphere((0,2,0),1),
+	sphere((0,2,3),2),
+	facet([Vector3(0,-3,-1),Vector3(0,-2,5),Vector3(5,4,0)]),
+	facet([Vector3(0,-3,-1),Vector3(0,-2,5),Vector3(-5,4,0)])
 ])
 
 vtkExporter = export.VTKExporter('vtkExporterTesting')

=== modified file 'examples/test/wall.py'
--- examples/test/wall.py	2012-06-28 19:34:29 +0000
+++ examples/test/wall.py	2013-03-28 11:13:12 +0000
@@ -1,15 +1,15 @@
 """
 Show basic wall functionality (infinite axis-aligned planes).
 """
-from yade import utils
+
 O.materials.append(FrictMat(young=30e9,density=1000,poisson=.2,frictionAngle=.5))
 O.bodies.append([
-	utils.wall(1,axis=2,sense=-1),
-	utils.wall(-5,axis=0,sense=1),
-	utils.wall(1,axis=1),
-	utils.wall((1,0,0),0),
-	utils.sphere([0,0,0],.5),
-	utils.sphere([-4,-4,-3],.5)
+	wall(1,axis=2,sense=-1),
+	wall(-5,axis=0,sense=1),
+	wall(1,axis=1),
+	wall((1,0,0),0),
+	sphere([0,0,0],.5),
+	sphere([-4,-4,-3],.5)
 ])
 Gl1_Wall(div=10)
 
@@ -29,14 +29,14 @@
 	NewtonIntegrator(damping=0.01,gravity=[1e2,1e2,1e2]),
 	]
 
-O.dt=utils.PWaveTimeStep()
+O.dt=PWaveTimeStep()
 O.save('/tmp/a.xml')
 O.saveTmp()
 
 O.run()
 #O.bodies.append([
-#	utils.facet([[-1,-1,0],[1,-1,0],[0,1,0]],dynamic=False,color=[1,0,0],young=1e3),
-#	utils.facet([[1,-1,0],[0,1,0,],[1,.5,.5]],dynamic=False,young=1e3)
+#	facet([[-1,-1,0],[1,-1,0],[0,1,0]],dynamic=False,color=[1,0,0],young=1e3),
+#	facet([[1,-1,0],[0,1,0,],[1,.5,.5]],dynamic=False,young=1e3)
 #])
 #import random
 

=== modified file 'examples/timeStepperUsage.py'
--- examples/timeStepperUsage.py	2012-08-24 11:19:25 +0000
+++ examples/timeStepperUsage.py	2013-05-14 21:24:11 +0000
@@ -13,7 +13,7 @@
 
 sp=pack.SpherePack()
 num=sp.makeCloud(Vector3().Zero,O.cell.refSize,rRelFuzz=.5,num=n,periodic=True,seed=1)
-O.bodies.append([utils.sphere(s[0],s[1]) for s in sp])
+O.bodies.append([sphere(s[0],s[1]) for s in sp])
 
 #make the problem more interesting by giving a smaller mass to one of the bodies, different stiffness present similar difficulties
 O.bodies[3].state.mass = O.bodies[n-1].state.mass*0.01
@@ -43,7 +43,7 @@
 
 #======   First, we won't use a timestepper at all, we fix O.dt using PWave timestep   =========#
 timing.reset()
-O.dt=0.8*utils.PWaveTimeStep() #for fair comparison, we use the same safety factor as in GS timestepper, allthough many scripts use 0.5 or even 0.1*utils.PWaveTimeStep()
+O.dt=0.8*PWaveTimeStep() #for fair comparison, we use the same safety factor as in GS timestepper, allthough many scripts use 0.5 or even 0.1*PWaveTimeStep()
 ts.active=False
 O.run(100000,True);#it will actually stop before 100k iterations as soon as the packing is stable
 print "--------------------------------"
@@ -66,7 +66,7 @@
 O.reload()
 timing.reset()
 O.dt=1000000 #or whatever
-#We force dt=1. The inertia of bodies will adjusted automaticaly...
+#We force dt=1. The inertia of bodies will adjusted automatically...
 newton.densityScaling=True
 #... but not that of cell, hence we have to adjust it or the problem becomes unstable
 triax.mass=triax.mass*(1e4)**2

=== modified file 'examples/triax-tutorial/script-session1.py'
--- examples/triax-tutorial/script-session1.py	2012-10-05 14:33:55 +0000
+++ examples/triax-tutorial/script-session1.py	2013-04-09 11:46:11 +0000
@@ -1,82 +1,95 @@
 # -*- coding: utf-8 -*-
+#*************************************************************************
+#  Copyright (C) 2010 by Bruno Chareyre                                  *
+#  bruno.chareyre_at_grenoble-inp.fr                                     *
+#                                                                        *
+#  This program is free software; it is licensed under the terms of the  *
+#  GNU General Public License v2 or later. See file LICENSE for details. *
+#*************************************************************************/
+
+## This script details the simulation of a triaxial test on sphere packings using Yade
+## See the associated pdf file for detailed exercises
+## the algorithms presented here have been used in published papers, namely:
+## * Chareyre et al. 2002 (http://www.geosyntheticssociety.org/Resources/Archive/GI/src/V9I2/GI-V9-N2-Paper1.pdf)
+## * Chareyre and Villard 2005 (https://yade-dem.org/w/images/1/1b/Chareyre&Villard2005_licensed.pdf)
+## * Scholtès et al. 2009 (http://dx.doi.org/10.1016/j.ijengsci.2008.07.002)
+## * Tong et al.2012 (http://dx.doi.org/10.2516/ogst/2012032)
+##
+## Most of the ideas were actually developped during my PhD.
+## If you want to know more on micro-macro relations evaluated by triaxial simulations
+## AND if you can read some french, it is here: http://tel.archives-ouvertes.fr/docs/00/48/68/07/PDF/Thesis.pdf
+
 from yade import pack
-#from utils import *
+
 ############################################
 ###   DEFINING VARIABLES AND MATERIALS   ###
 ############################################
 
 # The following 5 lines will be used later for batch execution
-nRead=utils.readParamsFromTable(
-	num_spheres=500,# number of spheres
+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
-compFricDegree = table.compFricDegree # contact friction during the confining phase
+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)
-key='_triax_base_' # put you simulation's name here
 young=5e6 # contact stiffness
 mn,mx=Vector3(0,0,0),Vector3(1,1,1) # corners of the initial packing
-thick = 0.01 # thickness of the plates
+
 
 ## 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=utils.aabbWalls([mn,mx],thickness=thick,material='walls')
+walls=aabbWalls([mn,mx],thickness=thick,material='walls')
 wallIds=O.bodies.append(walls)
 
 ## use a SpherePack object to generate a random loose particles packing
 sp=pack.SpherePack()
-sp.makeCloud(mn,mx,-1,0.3333,num_spheres,False, 0.95)
-
-## approximate mean rad of the futur dense packing for latter use (as an exercise: you can compute exact 
-volume = (mx[0]-mn[0])*(mx[1]-mn[1])*(mx[2]-mn[2])
-mean_rad = pow(0.09*volume/num_spheres,0.3333)
-
-
-clumps=False
+
+
+clumps=False #turn this true for the same example with clumps
 if clumps:
-	c1=pack.SpherePack([((-0.2*mean_rad,0,0),0.5*mean_rad),((0.2*mean_rad,0,0),0.5*mean_rad)])
-	sp.makeClumpCloud((0,0,0),(1,1,1),[c1],periodic=False)
-	O.bodies.append([utils.sphere(center,rad,material='spheres') for center,rad in sp])
-	standalone,clumps=sp.getClumps()
-	for clump in clumps:
-		O.bodies.clump(clump)
-		for i in clump[1:]: O.bodies[i].shape.color=O.bodies[clump[0]].shape.color
-	#sp.toSimulation()
+ ## approximate mean rad of the futur dense packing for latter use
+ volume = (mx[0]-mn[0])*(mx[1]-mn[1])*(mx[2]-mn[2])
+ mean_rad = pow(0.09*volume/num_spheres,0.3333)
+ ## define a unique clump type (we could have many, see clumpCloud documentation)
+ c1=pack.SpherePack([((-0.2*mean_rad,0,0),0.5*mean_rad),((0.2*mean_rad,0,0),0.5*mean_rad)])
+ ## generate positions and input them in the simulation
+ sp.makeClumpCloud(mn,mx,[c1],periodic=False)
+ sp.toSimulation(material='spheres')
 else:
-	O.bodies.append([utils.sphere(center,rad,material='spheres') for center,rad in sp])
-
-O.dt=.5*utils.PWaveTimeStep() # initial timestep, to not explode right away
-O.usesTimeStepper=True
+ sp.makeCloud(mn,mx,-1,0.3333,num_spheres,False, 0.95,seed=1) #"seed" make the "random" generation always the same
+ O.bodies.append([sphere(center,rad,material='spheres') for center,rad in sp])
+ #or alternatively (higher level function doing exactly the same):
+ #sp.toSimulation(material='spheres')
 
 ############################
 ###   DEFINING ENGINES   ###
 ############################
 
-triax=ThreeDTriaxialEngine(
+triax=TriaxialStressController(
 	## ThreeDTriaxialEngine will be used to control stress and strain. It controls particles size and plates positions.
+	## this control of boundary conditions was used for instance in http://dx.doi.org/10.1016/j.ijengsci.2008.07.002
 	maxMultiplier=1.+2e4/young, # spheres growing factor (fast growth)
 	finalMaxMultiplier=1.+2e3/young, # spheres growing factor (slow growth)
-	thickness = thick,
-	stressControl_1 = False, #switch stress/strain control
-	stressControl_2 = False,
-	stressControl_3 = False,
-	## The stress used for (isotropic) internal compaction
-	sigma_iso = 10000,
-	## Independant stress values for anisotropic loadings
-	sigma1=10000,
-	sigma2=10000,
-	sigma3=10000,
+	thickness = 0,
+	## switch stress/strain control using a bitmask. What is a bitmask, huh?!
+	## Say x=1 if stess is controlled on x, else x=0. Same for for y and z, which are 1 or 0.
+	## Then an integer uniquely defining the combination of all these tests is: mask = x*1 + y*2 + z*4
+	## to put it differently, the mask is the integer whose binary representation is xyz, i.e.
+	## "100" (1) means "x", "110" (3) means "x and y", "111" (7) means "x and y and z", etc.
+	stressMask = 7,
 	internalCompaction=True, # If true the confining pressure is generated by growing particles
-	Key=key, # passed to the engine so that the output file will have the correct name
 )
 
 newton=NewtonIntegrator(damping=damp)
@@ -89,9 +102,10 @@
 		[Ip2_FrictMat_FrictMat_FrictPhys()],
 		[Law2_ScGeom_FrictPhys_CundallStrack()]
 	),
-	GlobalStiffnessTimeStepper(active=1,timeStepUpdateInterval=100,timestepSafetyCoefficient=0.8, defaultDt=4*utils.PWaveTimeStep()),
+	## We will use the global stiffness of each body to determine an optimal timestep (see https://yade-dem.org/w/images/1/1b/Chareyre&Villard2005_licensed.pdf)
+	GlobalStiffnessTimeStepper(active=1,timeStepUpdateInterval=100,timestepSafetyCoefficient=0.8),
 	triax,
-	TriaxialStateRecorder(iterPeriod=100,file='WallStresses'+key),
+	TriaxialStateRecorder(iterPeriod=100,file='WallStresses'+table.key),
 	newton
 ]
 
@@ -99,24 +113,52 @@
 Gl1_Sphere.stripes=0
 if nRead==0: yade.qt.Controller(), yade.qt.View()
 
+## UNCOMMENT THE FOLLOWING SECTIONS ONE BY ONE
+## DEPENDING ON YOUR EDITOR, IT COULD BE DONE
+## BY SELECTING THE CODE BLOCKS BETWEEN THE SUBTITLES
+## AND PRESSING CTRL+SHIFT+D
+
 #######################################
 ###   APPLYING CONFINING PRESSURE   ###
 #######################################
 
+#the value of (isotropic) confining stress defines the target stress to be applied in all three directions
+triax.goal1=triax.goal2=triax.goal3=10000
+
 #while 1:
   #O.run(1000, True)
   ##the global unbalanced force on dynamic bodies, thus excluding boundaries, which are not at equilibrium
   #unb=unbalancedForce()
-  ##average stress
-  ##note: triax.stress(k) returns a stress vector, so we need to keep only the normal component
-  #meanS=(triax.stress(triax.wall_right_id)[0]+triax.stress(triax.wall_top_id)[1]+triax.stress(triax.wall_front_id)[2])/3
-  #print 'unbalanced force:',unb,' mean stress: ',meanS
-  #if unb<stabilityThreshold and abs(meanS-triax.sigma_iso)/triax.sigma_iso<0.001:
+  #print 'unbalanced force:',unb,' mean stress: ',triax.meanStress
+  #if unb<stabilityThreshold and abs(10000-triax.meanStress)/10000<0.001:
     #break
 
 #O.save('confinedState'+key+'.yade.gz')
 #print "###      Isotropic state saved      ###"
 
+###################################################
+###   REACHING A SPECIFIED POROSITY PRECISELY   ###
+###################################################
+
+### We will reach a prescribed value of porosity with the REFD algorithm
+### (see http://dx.doi.org/10.2516/ogst/2012032 and
+### http://www.geosyntheticssociety.org/Resources/Archive/GI/src/V9I2/GI-V9-N2-Paper1.pdf)
+
+#import sys #this is only for the flush() below
+#while triax.porosity>targetPorosity:
+	## we decrease friction value and apply it to all the bodies and contacts
+	#compFricDegree = 0.95*compFricDegree
+	#setContactFriction(radians(compFricDegree))
+	#print "\r Friction: ",compFricDegree," porosity:",triax.porosity,
+	#sys.stdout.flush()
+	## while we run steps, triax will tend to grow particles as the packing
+	## keeps shrinking as a consequence of decreasing friction. Consequently
+	## porosity will decrease
+	#O.run(500,1)
+
+#O.save('compactedState'+key+'.yade.gz')
+#print "###    Compacted state saved      ###"
+
 ##############################
 ###   DEVIATORIC LOADING   ###
 ##############################
@@ -125,24 +167,15 @@
 #triax.internalCompaction=False
 
 ## Change contact friction (remember that decreasing it would generate instantaneous instabilities)
-#triax.setContactProperties(finalFricDegree)
-
-##set independant stress control on each axis
-#triax.stressControl_1=triax.stressControl_2=triax.stressControl_3=True
-## We turn all these flags true, else boundaries will be fixed
-#triax.wall_bottom_activated=True
-#triax.wall_top_activated=True
-#triax.wall_left_activated=True
-#triax.wall_right_activated=True
-#triax.wall_back_activated=True
-#triax.wall_front_activated=True
-
-
-##If we want a triaxial loading at imposed strain rate, let's assign srain rate instead of stress
-#triax.stressControl_2=0 #we are tired of typing "True" and "False", we use implicit conversion from integer to boolean
-#triax.strainRate2=rate
-#triax.strainRate1=100*rate
-#triax.strainRate3=100*rate
+#setContactFriction(radians(finalFricDegree))
+
+##set stress control on x and z, we will impose strain rate on y
+#triax.stressMask = 5
+##now goal2 is the target strain rate
+#triax.goal2=-rate
+## we define the lateral stresses during the test, here the same 10kPa as for the initial confinement.
+#triax.goal1=10000
+#triax.goal3=10000
 
 ##we can change damping here. What is the effect in your opinion?
 #newton.damping=0.1
@@ -159,6 +192,7 @@
 ### a function saving variables
 #def history():
   	#plot.addData(e11=triax.strain[0], e22=triax.strain[1], e33=triax.strain[2],
+  		    #ev=-triax.strain[0]-triax.strain[1]-triax.strain[2],
 		    #s11=triax.stress(triax.wall_right_id)[0],
 		    #s22=triax.stress(triax.wall_top_id)[1],
 		    #s33=triax.stress(triax.wall_front_id)[2],
@@ -178,11 +212,15 @@
 
 ### declare what is to plot. "None" is for separating y and y2 axis
 #plot.plots={'i':('e11','e22','e33',None,'s11','s22','s33')}
-
-##display on the screen (doesn't work on VMware image it seems)
-##plot.plot()
-
-## In that case we can still save the data to a text file at the the end of the simulation, with: 
+### the traditional triaxial curves would be more like this:
+##plot.plots={'e22':('s11','s22','s33',None,'ev')}
+
+## display on the screen (doesn't work on VMware image it seems)
+#plot.plot()
+
+#####  PLAY THE SIMULATION HERE WITH "PLAY" BUTTON OR WITH THE COMMAND O.run(N)  #####
+
+## In that case we can still save the data to a text file at the the end of the simulation, with:
 #plot.saveDataTxt('results'+key)
 ##or even generate a script for gnuplot. Open another terminal and type  "gnuplot plotScriptKEY.gnuplot:
 #plot.saveGnuplot('plotScript'+key)

=== modified file 'examples/triax-tutorial/script-session2.py'
--- examples/triax-tutorial/script-session2.py	2012-10-05 14:33:55 +0000
+++ examples/triax-tutorial/script-session2.py	2013-03-28 11:33:07 +0000
@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 from yade import pack
-#from utils import *
 
 num_spheres=500
 ## corners of the initial packing
@@ -17,7 +16,7 @@
 O.materials.append(FrictMat(young=5e6,poisson=0.5,frictionAngle=0,density=0,label='walls'))
 
 ## create walls around the packing
-walls=utils.aabbWalls([mn,mx],thickness=thick,material='walls')
+walls=aabbWalls([mn,mx],thickness=thick,material='walls')
 wallIds=O.bodies.append(walls)
 
 sp=pack.SpherePack()
@@ -30,16 +29,16 @@
 if clumps:
 	c1=pack.SpherePack([((-0.2*mean_rad,0,0),0.5*mean_rad),((0.2*mean_rad,0,0),0.5*mean_rad)])
 	sp.makeClumpCloud((0,0,0),(1,1,1),[c1],periodic=False)
-	O.bodies.append([utils.sphere(center,rad,material='spheres') for center,rad in sp])
+	O.bodies.append([sphere(center,rad,material='spheres') for center,rad in sp])
 	standalone,clumps=sp.getClumps()
 	for clump in clumps:
 		O.bodies.clump(clump)
 		for i in clump[1:]: O.bodies[i].shape.color=O.bodies[clump[0]].shape.color
 	#sp.toSimulation()
 else:
-	O.bodies.append([utils.sphere(center,rad,material='spheres') for center,rad in sp])
+	O.bodies.append([sphere(center,rad,material='spheres') for center,rad in sp])
 
-O.dt=.5*utils.PWaveTimeStep() # initial timestep, to not explode right away
+O.dt=.5*PWaveTimeStep() # initial timestep, to not explode right away
 O.usesTimeStepper=True
 
 triax=ThreeDTriaxialEngine(
@@ -69,7 +68,7 @@
 		[Ip2_FrictMat_FrictMat_FrictPhys()],
 		[Law2_ScGeom_FrictPhys_CundallStrack()]
 	),
-	GlobalStiffnessTimeStepper(active=1,timeStepUpdateInterval=100,timestepSafetyCoefficient=0.8, defaultDt=4*utils.PWaveTimeStep()),
+	GlobalStiffnessTimeStepper(active=1,timeStepUpdateInterval=100,timestepSafetyCoefficient=0.8, defaultDt=4*PWaveTimeStep()),
 	triax,
 	TriaxialStateRecorder(iterPeriod=100,file='WallStresses'+key),
 	newton

=== modified file 'examples/triax-tutorial/session1-basic-triax.pdf'
Binary files examples/triax-tutorial/session1-basic-triax.pdf	2012-03-12 20:02:11 +0000 and examples/triax-tutorial/session1-basic-triax.pdf	2012-12-12 13:45:01 +0000 differ
=== removed file 'extra/boost_python_len.hpp'
--- extra/boost_python_len.hpp	2009-03-18 21:06:08 +0000
+++ extra/boost_python_len.hpp	1970-01-01 00:00:00 +0000
@@ -1,22 +0,0 @@
-#pragma once
-#include<boost/python/object.hpp>
-#include<boost/version.hpp>
-#if BOOST_VERSION<103400
-	// taken from boost-1.34/python/object.hpp
-
-	// Copyright David Abrahams 2002.
-	// Distributed under the Boost Software License, Version 1.0. (See
-	// accompanying file LICENSE_1_0.txt or copy at
-	// http://www.boost.org/LICENSE_1_0.txt)
-
-	namespace boost { namespace python {
-
-		 inline ssize_t len(object const& obj)
-		 {
-			  ssize_t result = PyObject_Length(obj.ptr());
-			  if (PyErr_Occurred()) throw_error_already_set();
-			  return result;
-		 }
-
-	}} // namespace boost::python
-#endif // BOOST_VERSION<103400

=== removed file 'extra/foreach.hpp_local'
--- extra/foreach.hpp_local	2009-03-18 21:06:08 +0000
+++ extra/foreach.hpp_local	1970-01-01 00:00:00 +0000
@@ -1,812 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// foreach.hpp header file
-//
-// Copyright 2004 Eric Niebler.
-// Distributed under the Boost Software License, Version 1.0. (See
-// accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// Credits:
-//  Anson Tsao        - for the initial inspiration and several good suggestions.
-//  Thorsten Ottosen  - for Boost.Range, and for suggesting a way to detect
-//                      const-qualified rvalues at compile time on VC7.1+
-//  Russell Hind      - For help porting to Borland
-//  Alisdair Meredith - For help porting to Borland
-//  Stefan Slapeta    - For help porting to Intel
-
-#ifndef BOOST_FOREACH
-
-// MS compatible compilers support #pragma once
-#if defined(_MSC_VER) && (_MSC_VER >= 1020)
-# pragma once
-#endif
-
-#include <cstddef>
-#include <utility>  // for std::pair
-
-#include <boost/config.hpp>
-#include <boost/detail/workaround.hpp>
-
-// Some compilers let us detect even const-qualified rvalues at compile-time
-#if BOOST_WORKAROUND(BOOST_MSVC, >= 1310)                                                       \
- || (BOOST_WORKAROUND(__GNUC__, >= 4) && !defined(BOOST_INTEL))                                 \
- || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ >= 4) && !defined(BOOST_INTEL))
-# define BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION
-#else
-// Some compilers allow temporaries to be bound to non-const references.
-// These compilers make it impossible to for BOOST_FOREACH to detect
-// temporaries and avoid reevaluation of the collection expression.
-# if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)                                                      \
-  || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))                                     \
-  || (BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700) && defined(_MSC_VER))                   \
-  || BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570))                                      \
-  || BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(60590042))
-#  define BOOST_FOREACH_NO_RVALUE_DETECTION
-# endif
-// Some compilers do not correctly implement the lvalue/rvalue conversion
-// rules of the ternary conditional operator.
-# if defined(BOOST_FOREACH_NO_RVALUE_DETECTION)                                                 \
-  || defined(BOOST_NO_SFINAE)                                                                   \
-  || BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400))                                        \
-  || BOOST_WORKAROUND(BOOST_INTEL_WIN, <= 810)                                                  \
-  || BOOST_WORKAROUND(__GNUC__, < 3)                                                            \
-  || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 2))                                \
-  || (BOOST_WORKAROUND(__GNUC__, == 3) && (__GNUC_MINOR__ <= 3) && defined(__APPLE_CC__))       \
-  || BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))                                         \
-  || BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3206))
-#  define BOOST_FOREACH_NO_CONST_RVALUE_DETECTION
-# else
-#  define BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
-# endif
-#endif
-
-#include <boost/mpl/if.hpp>
-#include <boost/mpl/logical.hpp>
-#include <boost/mpl/eval_if.hpp>
-#include <boost/noncopyable.hpp>
-#include <boost/range/end.hpp>
-#include <boost/range/begin.hpp>
-#include <boost/range/result_iterator.hpp>
-#include <boost/type_traits/is_array.hpp>
-#include <boost/type_traits/is_const.hpp>
-#include <boost/type_traits/is_abstract.hpp>
-#include <boost/type_traits/is_base_and_derived.hpp>
-#include <boost/iterator/iterator_traits.hpp>
-#include <boost/utility/addressof.hpp>
-
-#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
-# include <new>
-# include <boost/aligned_storage.hpp>
-# include <boost/utility/enable_if.hpp>
-# include <boost/type_traits/remove_const.hpp>
-#endif
-
-// This must be at global scope, hence the uglified name
-enum boost_foreach_argument_dependent_lookup_hack
-{
-    boost_foreach_argument_dependent_lookup_hack_value
-};
-
-namespace boost
-{
-
-// forward declarations for iterator_range
-template<typename T>
-class iterator_range;
-
-// forward declarations for sub_range
-template<typename T>
-class sub_range;
-
-namespace foreach
-{
-    ///////////////////////////////////////////////////////////////////////////////
-    // in_range
-    //
-    template<typename T>
-    inline std::pair<T, T> in_range(T begin, T end)
-    {
-        return std::make_pair(begin, end);
-    }
-
-    ///////////////////////////////////////////////////////////////////////////////
-    // boost::foreach::tag
-    //
-    typedef boost_foreach_argument_dependent_lookup_hack tag;
-
-    ///////////////////////////////////////////////////////////////////////////////
-    // boost::foreach::is_lightweight_proxy
-    //   Specialize this for user-defined collection types if they are inexpensive to copy.
-    //   This tells BOOST_FOREACH it can avoid the rvalue/lvalue detection stuff.
-    template<typename T>
-    struct is_lightweight_proxy
-      : boost::mpl::false_
-    {
-    };
-
-    ///////////////////////////////////////////////////////////////////////////////
-    // boost::foreach::is_noncopyable
-    //   Specialize this for user-defined collection types if they cannot be copied.
-    //   This also tells BOOST_FOREACH to avoid the rvalue/lvalue detection stuff.
-    template<typename T>
-    struct is_noncopyable
-    #if !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED) && !defined(BOOST_NO_IS_ABSTRACT)
-      : boost::mpl::or_<
-            boost::is_abstract<T>
-          , boost::is_base_and_derived<boost::noncopyable, T>
-        >
-    #elif !defined(BOOST_BROKEN_IS_BASE_AND_DERIVED)
-      : boost::is_base_and_derived<boost::noncopyable, T>
-    #elif !defined(BOOST_NO_IS_ABSTRACT)
-      : boost::is_abstract<T>
-    #else
-      : boost::mpl::false_
-    #endif
-    {
-    };
-
-} // namespace foreach
-
-} // namespace boost
-
-// vc6/7 needs help ordering the following overloads
-#ifdef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-# define BOOST_FOREACH_TAG_DEFAULT ...
-#else
-# define BOOST_FOREACH_TAG_DEFAULT boost::foreach::tag
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// boost_foreach_is_lightweight_proxy
-//   Another customization point for the is_lightweight_proxy optimization,
-//   this one works on legacy compilers. Overload boost_foreach_is_lightweight_proxy
-//   at the global namespace for your type.
-template<typename T>
-inline boost::foreach::is_lightweight_proxy<T> *
-boost_foreach_is_lightweight_proxy(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; }
-
-template<typename T>
-inline boost::mpl::true_ *
-boost_foreach_is_lightweight_proxy(std::pair<T, T> *&, boost::foreach::tag) { return 0; }
-
-template<typename T>
-inline boost::mpl::true_ *
-boost_foreach_is_lightweight_proxy(boost::iterator_range<T> *&, boost::foreach::tag) { return 0; }
-
-template<typename T>
-inline boost::mpl::true_ *
-boost_foreach_is_lightweight_proxy(boost::sub_range<T> *&, boost::foreach::tag) { return 0; }
-
-template<typename T>
-inline boost::mpl::true_ *
-boost_foreach_is_lightweight_proxy(T **&, boost::foreach::tag) { return 0; }
-
-///////////////////////////////////////////////////////////////////////////////
-// boost_foreach_is_noncopyable
-//   Another customization point for the is_noncopyable trait,
-//   this one works on legacy compilers. Overload boost_foreach_is_noncopyable
-//   at the global namespace for your type.
-template<typename T>
-inline boost::foreach::is_noncopyable<T> *
-boost_foreach_is_noncopyable(T *&, BOOST_FOREACH_TAG_DEFAULT) { return 0; }
-
-namespace boost
-{
-
-namespace foreach_detail_
-{
-
-///////////////////////////////////////////////////////////////////////////////
-// Define some utilities for assessing the properties of expressions
-//
-typedef char yes_type;
-typedef char (&no_type)[2];
-yes_type is_true(boost::mpl::true_ *);
-no_type is_true(boost::mpl::false_ *);
-
-// Extracts the desired property from the expression without evaluating it
-#define BOOST_FOREACH_PROTECT(expr)                                                             \
-    (static_cast<boost::mpl::bool_<1 == sizeof(boost::foreach_detail_::is_true(expr))> *>(0))
-
-template<typename Bool1, typename Bool2>
-inline boost::mpl::and_<Bool1, Bool2> *and_(Bool1 *, Bool2 *) { return 0; }
-
-template<typename Bool1, typename Bool2, typename Bool3>
-inline boost::mpl::and_<Bool1, Bool2, Bool3> *and_(Bool1 *, Bool2 *, Bool3 *) { return 0; }
-
-template<typename Bool1, typename Bool2>
-inline boost::mpl::or_<Bool1, Bool2> *or_(Bool1 *, Bool2 *) { return 0; }
-
-template<typename Bool1, typename Bool2, typename Bool3>
-inline boost::mpl::or_<Bool1, Bool2, Bool3> *or_(Bool1 *, Bool2 *, Bool3 *) { return 0; }
-
-template<typename Bool>
-inline boost::mpl::not_<Bool> *not_(Bool *) { return 0; }
-
-template<typename T>
-inline boost::mpl::false_ *is_rvalue_(T &, int) { return 0; }
-
-template<typename T>
-inline boost::mpl::true_ *is_rvalue_(T const &, ...) { return 0; }
-
-template<typename T>
-inline boost::is_array<T> *is_array_(T const &) { return 0; }
-
-template<typename T>
-inline boost::is_const<T> *is_const_(T &) { return 0; }
-
-#ifndef BOOST_FOREACH_NO_RVALUE_DETECTION
-template<typename T>
-inline boost::mpl::true_ *is_const_(T const &) { return 0; }
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// auto_any_t/auto_any
-//  General utility for putting an object of any type into automatic storage
-struct auto_any_base
-{
-    // auto_any_base must evaluate to false in boolean context so that
-    // they can be declared in if() statements.
-    operator bool() const
-    {
-        return false;
-    }
-};
-
-template<typename T>
-struct auto_any : auto_any_base
-{
-    auto_any(T const &t)
-      : item(t)
-    {
-    }
-
-    // temporaries of type auto_any will be bound to const auto_any_base
-    // references, but we still want to be able to mutate the stored
-    // data, so declare it as mutable.
-    mutable T item;
-};
-
-typedef auto_any_base const &auto_any_t;
-
-template<typename T, typename C>
-inline BOOST_DEDUCED_TYPENAME boost::mpl::if_<C, T const, T>::type &auto_any_cast(auto_any_t a)
-{
-    return static_cast<auto_any<T> const &>(a).item;
-}
-
-typedef boost::mpl::true_ const_;
-
-///////////////////////////////////////////////////////////////////////////////
-// type2type
-//
-template<typename T, typename C = boost::mpl::false_>
-struct type2type
-  : boost::mpl::if_<C, T const, T>
-{
-};
-
-template<typename T, typename C = boost::mpl::false_>
-struct foreach_iterator
-{
-    typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if<
-        C
-      , range_const_iterator<T>
-      , range_iterator<T>
-    >::type type;
-};
-
-template<typename T, typename C = boost::mpl::false_>
-struct foreach_reference
-  : iterator_reference<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
-{
-};
-
-///////////////////////////////////////////////////////////////////////////////
-// encode_type
-//
-template<typename T>
-inline type2type<T> *encode_type(T &, boost::mpl::false_ *) { return 0; }
-
-template<typename T>
-inline type2type<T, const_> *encode_type(T const &, boost::mpl::true_ *) { return 0; }
-
-///////////////////////////////////////////////////////////////////////////////
-// set_false
-//
-inline bool set_false(bool &b) { return b = false; }
-
-///////////////////////////////////////////////////////////////////////////////
-// to_ptr
-//
-template<typename T>
-inline T *&to_ptr(T const &)
-{
-    static T *t = 0;
-    return t;
-}
-
-// Borland needs a little extra help with arrays
-#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
-template<typename T,std::size_t N>
-inline T (*&to_ptr(T (&)[N]))[N]
-{
-    static T (*t)[N] = 0;
-    return t;
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// derefof
-//
-template<typename T>
-inline T &derefof(T *t)
-{
-    // This is a work-around for a compiler bug in Borland. If T* is a pointer to array type U(*)[N],
-    // then dereferencing it results in a U* instead of U(&)[N]. The cast forces the issue.
-    return reinterpret_cast<T &>(
-        *const_cast<char *>(
-            reinterpret_cast<char const volatile *>(t)
-        )
-    );
-}
-
-#ifdef BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION
-///////////////////////////////////////////////////////////////////////////////
-// Detect at compile-time whether an expression yields an rvalue or
-// an lvalue. This is rather non-standard, but some popular compilers
-// accept it.
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// rvalue_probe
-//
-template<typename T>
-struct rvalue_probe
-{
-    struct private_type_ {};
-    // can't ever return an array by value
-    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
-        boost::mpl::or_<boost::is_abstract<T>, boost::is_array<T> >, private_type_, T
-    >::type value_type;
-    operator value_type();
-    operator T &() const;
-};
-
-template<typename T>
-rvalue_probe<T> const make_probe(T const &t);
-
-# define BOOST_FOREACH_IS_RVALUE(COL)                                                           \
-    boost::foreach_detail_::and_(                                                               \
-        boost::foreach_detail_::not_(boost::foreach_detail_::is_array_(COL))                    \
-      , BOOST_FOREACH_PROTECT(boost::foreach_detail_::is_rvalue_(                               \
-            (true ? boost::foreach_detail_::make_probe(COL) : (COL)), 0)))
-
-#elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION)
-///////////////////////////////////////////////////////////////////////////////
-// Detect at run-time whether an expression yields an rvalue
-// or an lvalue. This is 100% standard C++, but not all compilers
-// accept it. Also, it causes FOREACH to break when used with non-
-// copyable collection types.
-///////////////////////////////////////////////////////////////////////////////
-
-///////////////////////////////////////////////////////////////////////////////
-// rvalue_probe
-//
-template<typename T>
-struct rvalue_probe
-{
-    rvalue_probe(T &t, bool &b)
-      : value(t)
-      , is_rvalue(b)
-    {
-    }
-
-    struct private_type_ {};
-    // can't ever return an array or an abstract type by value
-    #ifdef BOOST_NO_IS_ABSTRACT
-    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
-        boost::is_array<T>, private_type_, T
-    >::type value_type;
-    #else
-    typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_<
-        boost::mpl::or_<boost::is_abstract<T>, boost::is_array<T> >, private_type_, T
-    >::type value_type;
-    #endif
-    
-    operator value_type()
-    {
-        this->is_rvalue = true;
-        return this->value;
-    }
-
-    operator T &() const
-    {
-        return this->value;
-    }
-
-private:
-    T &value;
-    bool &is_rvalue;
-};
-
-template<typename T>
-rvalue_probe<T> make_probe(T &t, bool &b) { return rvalue_probe<T>(t, b); }
-
-template<typename T>
-rvalue_probe<T const> make_probe(T const &t, bool &b)  { return rvalue_probe<T const>(t, b); }
-
-///////////////////////////////////////////////////////////////////////////////
-// simple_variant
-//  holds either a T or a T const*
-template<typename T>
-struct simple_variant
-{
-    simple_variant(T const *t)
-      : is_rvalue(false)
-    {
-        *static_cast<T const **>(this->data.address()) = t;
-    }
-
-    simple_variant(T const &t)
-      : is_rvalue(true)
-    {
-        ::new(this->data.address()) T(t);
-    }
-
-    simple_variant(simple_variant const &that)
-      : is_rvalue(that.is_rvalue)
-    {
-        if(this->is_rvalue)
-            ::new(this->data.address()) T(*that.get());
-        else
-            *static_cast<T const **>(this->data.address()) = that.get();
-    }
-
-    ~simple_variant()
-    {
-        if(this->is_rvalue)
-            this->get()->~T();
-    }
-
-    T const *get() const
-    {
-        if(this->is_rvalue)
-            return static_cast<T const *>(this->data.address());
-        else
-            return *static_cast<T const * const *>(this->data.address());
-    }
-
-private:
-    enum size_type { size = sizeof(T) > sizeof(T*) ? sizeof(T) : sizeof(T*) };
-    simple_variant &operator =(simple_variant const &); 
-    bool const is_rvalue;
-    aligned_storage<size> data;
-};
-
-// If the collection is an array or is noncopyable, it must be an lvalue.
-// If the collection is a lightweight proxy, treat it as an rvalue
-// BUGBUG what about a noncopyable proxy?
-template<typename LValue, typename IsProxy>
-inline BOOST_DEDUCED_TYPENAME boost::enable_if<boost::mpl::or_<LValue, IsProxy>, IsProxy>::type *
-should_copy_impl(LValue *, IsProxy *, bool *)
-{
-    return 0;
-}
-
-// Otherwise, we must determine at runtime whether it's an lvalue or rvalue
-inline bool *
-should_copy_impl(boost::mpl::false_ *, boost::mpl::false_ *, bool *is_rvalue)
-{
-    return is_rvalue;
-}
-
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// contain
-//
-template<typename T>
-inline auto_any<T> contain(T const &t, boost::mpl::true_ *) // rvalue
-{
-    return t;
-}
-
-template<typename T>
-inline auto_any<T *> contain(T &t, boost::mpl::false_ *) // lvalue
-{
-    // Cannot seem to get sunpro to handle addressof() with array types.
-    #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x570))
-    return &t;
-    #else
-    return boost::addressof(t);
-    #endif
-}
-
-#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
-template<typename T>
-auto_any<simple_variant<T> >
-contain(T const &t, bool *rvalue)
-{
-    return *rvalue ? simple_variant<T>(t) : simple_variant<T>(&t);
-}
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// begin
-//
-template<typename T, typename C>
-inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
-begin(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue
-{
-    return boost::begin(auto_any_cast<T, C>(col));
-}
-
-template<typename T, typename C>
-inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
-begin(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue
-{
-    typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type;
-    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator;
-    return iterator(boost::begin(derefof(auto_any_cast<type *, boost::mpl::false_>(col))));
-}
-
-#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
-template<typename T>
-auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>
-begin(auto_any_t col, type2type<T, const_> *, bool *)
-{
-    return boost::begin(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get());
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// end
-//
-template<typename T, typename C>
-inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
-end(auto_any_t col, type2type<T, C> *, boost::mpl::true_ *) // rvalue
-{
-    return boost::end(auto_any_cast<T, C>(col));
-}
-
-template<typename T, typename C>
-inline auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type>
-end(auto_any_t col, type2type<T, C> *, boost::mpl::false_ *) // lvalue
-{
-    typedef BOOST_DEDUCED_TYPENAME type2type<T, C>::type type;
-    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iterator;
-    return iterator(boost::end(derefof(auto_any_cast<type *, boost::mpl::false_>(col))));
-}
-
-#ifdef BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION
-template<typename T>
-auto_any<BOOST_DEDUCED_TYPENAME foreach_iterator<T, const_>::type>
-end(auto_any_t col, type2type<T, const_> *, bool *)
-{
-    return boost::end(*auto_any_cast<simple_variant<T>, boost::mpl::false_>(col).get());
-}
-#endif
-
-#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-template<typename T, typename C>
-inline auto_any<int>
-end(auto_any_t col, type2type<T *, C> *, boost::mpl::true_ *) // null-terminated C-style strings
-{
-    return 0; // not used
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// done
-//
-template<typename T, typename C>
-inline bool done(auto_any_t cur, auto_any_t end, type2type<T, C> *)
-{
-    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t;
-    return auto_any_cast<iter_t, boost::mpl::false_>(cur) == auto_any_cast<iter_t, boost::mpl::false_>(end);
-}
-
-#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
-template<typename T, typename C>
-inline bool done(auto_any_t cur, auto_any_t, type2type<T *, C> *) // null-terminated C-style strings
-{
-    return ! *auto_any_cast<T *, boost::mpl::false_>(cur);
-}
-#endif
-
-///////////////////////////////////////////////////////////////////////////////
-// next
-//
-template<typename T, typename C>
-inline void next(auto_any_t cur, type2type<T, C> *)
-{
-    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t;
-    ++auto_any_cast<iter_t, boost::mpl::false_>(cur);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// deref
-//
-template<typename T, typename C>
-inline BOOST_DEDUCED_TYPENAME foreach_reference<T, C>::type
-deref(auto_any_t cur, type2type<T, C> *)
-{
-    typedef BOOST_DEDUCED_TYPENAME foreach_iterator<T, C>::type iter_t;
-    return *auto_any_cast<iter_t, boost::mpl::false_>(cur);
-}
-
-} // namespace foreach_detail_
-} // namespace boost
-
-// A sneaky way to get the type of the collection without evaluating the expression
-#define BOOST_FOREACH_TYPEOF(COL)                                                               \
-    (true ? 0 : boost::foreach_detail_::encode_type(COL, boost::foreach_detail_::is_const_(COL)))
-
-// returns true_* if the type is noncopyable
-#define BOOST_FOREACH_IS_NONCOPYABLE(COL)                                                       \
-    boost_foreach_is_noncopyable(                                                               \
-        boost::foreach_detail_::to_ptr(COL)                                                     \
-      , boost_foreach_argument_dependent_lookup_hack_value)
-
-// returns true_* if the type is a lightweight proxy (and is not noncopyable)
-#define BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)                                                 \
-    boost::foreach_detail_::and_(                                                               \
-        boost::foreach_detail_::not_(BOOST_FOREACH_IS_NONCOPYABLE(COL))                         \
-      , boost_foreach_is_lightweight_proxy(                                                     \
-            boost::foreach_detail_::to_ptr(COL)                                                 \
-          , boost_foreach_argument_dependent_lookup_hack_value))
-
-#ifdef BOOST_FOREACH_COMPILE_TIME_CONST_RVALUE_DETECTION
-///////////////////////////////////////////////////////////////////////////////
-// R-values and const R-values supported here with zero runtime overhead
-///////////////////////////////////////////////////////////////////////////////
-
-// No variable is needed to track the rvalue-ness of the collection expression
-# define BOOST_FOREACH_PREAMBLE()                                                               \
-    /**/
-
-// Evaluate the collection expression
-# define BOOST_FOREACH_EVALUATE(COL)                                                            \
-    (COL)
-
-# define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
-    (true ? 0 : boost::foreach_detail_::or_(                                                    \
-        BOOST_FOREACH_IS_RVALUE(COL)                                                            \
-      , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)))
-
-#elif defined(BOOST_FOREACH_RUN_TIME_CONST_RVALUE_DETECTION)
-///////////////////////////////////////////////////////////////////////////////
-// R-values and const R-values supported here
-///////////////////////////////////////////////////////////////////////////////
-
-// Declare a variable to track the rvalue-ness of the collection expression
-# define BOOST_FOREACH_PREAMBLE()                                                               \
-    if (bool _foreach_is_rvalue = false) {} else
-
-// Evaluate the collection expression, and detect if it is an lvalue or and rvalue
-# define BOOST_FOREACH_EVALUATE(COL)                                                            \
-    (true ? boost::foreach_detail_::make_probe((COL), _foreach_is_rvalue) : (COL))
-
-// The rvalue/lvalue-ness of the collection expression is determined dynamically, unless
-// type type is an array or is noncopyable or is non-const, in which case we know it's an lvalue.
-// If the type happens to be a lightweight proxy, always make a copy.
-# define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
-    (boost::foreach_detail_::should_copy_impl(                                                  \
-        true ? 0 : boost::foreach_detail_::or_(                                                 \
-            boost::foreach_detail_::is_array_(COL)                                              \
-          , BOOST_FOREACH_IS_NONCOPYABLE(COL)                                                   \
-          , boost::foreach_detail_::not_(boost::foreach_detail_::is_const_(COL)))               \
-      , true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)                                      \
-      , &_foreach_is_rvalue))
-
-#elif !defined(BOOST_FOREACH_NO_RVALUE_DETECTION)
-///////////////////////////////////////////////////////////////////////////////
-// R-values supported here, const R-values NOT supported here
-///////////////////////////////////////////////////////////////////////////////
-
-// No variable is needed to track the rvalue-ness of the collection expression
-# define BOOST_FOREACH_PREAMBLE()                                                               \
-    /**/
-
-// Evaluate the collection expression
-# define BOOST_FOREACH_EVALUATE(COL)                                                            \
-    (COL)
-
-// Determine whether the collection expression is an lvalue or an rvalue.
-// NOTE: this gets the answer wrong for const rvalues.
-# define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
-    (true ? 0 : boost::foreach_detail_::or_(                                                    \
-        boost::foreach_detail_::is_rvalue_((COL), 0)                                            \
-      , BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL)))
-
-#else
-///////////////////////////////////////////////////////////////////////////////
-// R-values NOT supported here
-///////////////////////////////////////////////////////////////////////////////
-
-// No variable is needed to track the rvalue-ness of the collection expression
-# define BOOST_FOREACH_PREAMBLE()                                                               \
-    /**/
-
-// Evaluate the collection expression
-# define BOOST_FOREACH_EVALUATE(COL)                                                            \
-    (COL)
-
-// Can't use rvalues with BOOST_FOREACH (unless they are lightweight proxies)
-# define BOOST_FOREACH_SHOULD_COPY(COL)                                                         \
-    (true ? 0 : BOOST_FOREACH_IS_LIGHTWEIGHT_PROXY(COL))
-
-#endif
-
-#define BOOST_FOREACH_CONTAIN(COL)                                                              \
-    boost::foreach_detail_::contain(                                                            \
-        BOOST_FOREACH_EVALUATE(COL)                                                             \
-      , BOOST_FOREACH_SHOULD_COPY(COL))
-
-#define BOOST_FOREACH_BEGIN(COL)                                                                \
-    boost::foreach_detail_::begin(                                                              \
-        _foreach_col                                                                            \
-      , BOOST_FOREACH_TYPEOF(COL)                                                               \
-      , BOOST_FOREACH_SHOULD_COPY(COL))
-
-#define BOOST_FOREACH_END(COL)                                                                  \
-    boost::foreach_detail_::end(                                                                \
-        _foreach_col                                                                            \
-      , BOOST_FOREACH_TYPEOF(COL)                                                               \
-      , BOOST_FOREACH_SHOULD_COPY(COL))
-
-#define BOOST_FOREACH_DONE(COL)                                                                 \
-    boost::foreach_detail_::done(                                                               \
-        _foreach_cur                                                                            \
-      , _foreach_end                                                                            \
-      , BOOST_FOREACH_TYPEOF(COL))
-
-#define BOOST_FOREACH_NEXT(COL)                                                                 \
-    boost::foreach_detail_::next(                                                               \
-        _foreach_cur                                                                            \
-      , BOOST_FOREACH_TYPEOF(COL))
-
-#define BOOST_FOREACH_DEREF(COL)                                                                \
-    boost::foreach_detail_::deref(                                                              \
-        _foreach_cur                                                                            \
-      , BOOST_FOREACH_TYPEOF(COL))
-
-///////////////////////////////////////////////////////////////////////////////
-// BOOST_FOREACH
-//
-//   For iterating over collections. Collections can be
-//   arrays, null-terminated strings, or STL containers.
-//   The loop variable can be a value or reference. For
-//   example:
-//
-//   std::list<int> int_list(/*stuff*/);
-//   BOOST_FOREACH(int &i, int_list)
-//   {
-//       /* 
-//        * loop body goes here.
-//        * i is a reference to the int in int_list.
-//        */
-//   }
-//
-//   Alternately, you can declare the loop variable first,
-//   so you can access it after the loop finishes. Obviously,
-//   if you do it this way, then the loop variable cannot be
-//   a reference.
-//
-//   int i;
-//   BOOST_FOREACH(i, int_list)
-//       { ... }
-//
-#define BOOST_FOREACH(VAR, COL)                                                                 \
-    BOOST_FOREACH_PREAMBLE()                                                                    \
-    if (boost::foreach_detail_::auto_any_t _foreach_col = BOOST_FOREACH_CONTAIN(COL)) {} else   \
-    if (boost::foreach_detail_::auto_any_t _foreach_cur = BOOST_FOREACH_BEGIN(COL)) {} else     \
-    if (boost::foreach_detail_::auto_any_t _foreach_end = BOOST_FOREACH_END(COL)) {} else       \
-    for (bool _foreach_continue = true;                                                         \
-              _foreach_continue && !BOOST_FOREACH_DONE(COL);                                    \
-              _foreach_continue ? BOOST_FOREACH_NEXT(COL) : (void)0)                            \
-        if  (boost::foreach_detail_::set_false(_foreach_continue)) {} else                      \
-        for (VAR = BOOST_FOREACH_DEREF(COL); !_foreach_continue; _foreach_continue = true)
-
-#endif

=== modified file 'gui/qt4/GLViewer.cpp'
--- gui/qt4/GLViewer.cpp	2012-11-01 21:42:22 +0000
+++ gui/qt4/GLViewer.cpp	2013-03-07 18:28:01 +0000
@@ -407,8 +407,8 @@
 			min=Vector3r(inf,inf,inf); max=Vector3r(-inf,-inf,-inf);
 			FOREACH(const shared_ptr<Body>& b, *rb->bodies){
 				if(!b) continue;
-				max=max.cwise().max(b->state->pos);
-				min=min.cwise().min(b->state->pos);
+				max=max.cwiseMax(b->state->pos);
+				min=min.cwiseMin(b->state->pos);
 			}
 			if(isinf(min[0])||isinf(min[1])||isinf(min[2])||isinf(max[0])||isinf(max[1])||isinf(max[2])){ LOG_DEBUG("No min/max computed from bodies either, setting cube (-1,-1,-1)×(1,1,1)"); min=-Vector3r::Ones(); max=Vector3r::Ones(); }
 		} else {LOG_DEBUG("Using scene's Aabb");}

=== modified file 'gui/qt4/GLViewer.hpp'
--- gui/qt4/GLViewer.hpp	2012-11-01 21:42:22 +0000
+++ gui/qt4/GLViewer.hpp	2013-03-14 20:01:49 +0000
@@ -2,16 +2,15 @@
 // © 2008 Václav Šmilauer
 #pragma once
 
+#ifndef Q_MOC_RUN 
 #include<yade/core/Omega.hpp>
-
-#ifndef Q_MOC_RUN 
 #include<yade/pkg/common/OpenGLRenderer.hpp>
 #include<yade/pkg/common/PeriodicEngines.hpp>
+#include<boost/date_time/posix_time/posix_time.hpp>
 #endif 
 
 #include<QGLViewer/qglviewer.h>
 #include<QGLViewer/constraint.h>
-#include<boost/date_time/posix_time/posix_time.hpp>
 #include<set>
 
 /*! Class handling user interaction with the openGL rendering of simulation.

=== modified file 'gui/qt4/SerializableEditor.py'
--- gui/qt4/SerializableEditor.py	2011-01-30 15:43:18 +0000
+++ gui/qt4/SerializableEditor.py	2013-03-18 20:03:32 +0000
@@ -2,16 +2,20 @@
 from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from PyQt4 import QtGui
-#from PyQt4 import Qwt5
 
 import re,itertools
 import logging
 logging.trace=logging.debug
 logging.basicConfig(level=logging.INFO)
-#from logging import debug,info,warning,error
+
 from yade import *
 import yade.qt
 
+try:
+  from minieigen import *
+except ImportError:
+  from miniEigen import *
+
 seqSerializableShowType=True # show type headings in serializable sequences (takes vertical space, but makes the type hyperlinked)
 
 # BUG: cursor is moved to the beginnign of the input field even if it has focus

=== modified file 'lib/base/Math.hpp'
--- lib/base/Math.hpp	2012-09-21 19:03:18 +0000
+++ lib/base/Math.hpp	2013-03-07 18:28:01 +0000
@@ -14,7 +14,6 @@
 // disable optimization which are "unsafe":
 // eigen objects cannot be passed by-value, otherwise they will no be aligned
 
-#define EIGEN2_SUPPORT  // This makes Eigen3 migration easier
 #define EIGEN_DONT_VECTORIZE
 #define EIGEN_DONT_ALIGN
 #define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
@@ -22,26 +21,12 @@
 
 #include<Eigen/Core>
 #include<Eigen/Geometry>
-#if EIGEN_WORLD_VERSION==2
-	#include<Eigen/Array>
-#endif
 #include<Eigen/QR>
 #include<Eigen/LU>
 #include<Eigen/SVD>
+#include<Eigen/Eigenvalues>
 #include<float.h>
 
-// USING_PART_OF_NAMESPACE_EIGEN
-//using namespace eigen; // for eigen3
-// 
-
-// mimick expectation macros that linux has (see e.g. http://kerneltrap.org/node/4705)
-#ifndef likely
-	#define likely(x) __builtin_expect(!!(x),1)
-#endif
-#ifndef unlikely
-	#define unlikely(x) __builtin_expect(!!(x),1)
-#endif
-
 // templates of those types with single parameter are not possible, use macros for now
 #define VECTOR2_TEMPLATE(Scalar) Eigen::Matrix<Scalar,2,1>
 #define VECTOR3_TEMPLATE(Scalar) Eigen::Matrix<Scalar,3,1>

=== modified file 'lib/base/openmp-accu.hpp'
--- lib/base/openmp-accu.hpp	2012-06-05 18:39:34 +0000
+++ lib/base/openmp-accu.hpp	2013-03-28 19:18:22 +0000
@@ -92,7 +92,7 @@
 		int eSize; // size of an element, computed from cache line size and sizeof(T)
 		char* data; // use void* rather than T*, since with T* the pointer arithmetics has sizeof(T) as unit, which is confusing; char* takes one byte
 	public:
-	// initialize storage with _zeroValue, depending on muber of threads
+	// initialize storage with _zeroValue, depending on number of threads
 	OpenMPAccumulator(): CLS(sysconf(_SC_LEVEL1_DCACHE_LINESIZE)>0 ? sysconf(_SC_LEVEL1_DCACHE_LINESIZE) : 64), nThreads(omp_get_max_threads()), eSize(CLS*(sizeof(T)/CLS+(sizeof(T)%CLS==0 ? 0 :1))) {
 		int succ=posix_memalign(/*where allocated*/(void**)&data,/*alignment*/CLS,/*size*/ nThreads*eSize);
 		if(succ!=0) throw std::runtime_error("OpenMPAccumulator: posix_memalign failed to allocate memory.");

=== modified file 'lib/smoothing/WeightedAverage2d.hpp'
--- lib/smoothing/WeightedAverage2d.hpp	2010-11-07 11:46:20 +0000
+++ lib/smoothing/WeightedAverage2d.hpp	2013-03-07 18:28:16 +0000
@@ -2,14 +2,6 @@
 
 #pragma once
 
-// temporary fix:
-// clang #includes  first /usr/include/c++/4.4/fenv.h, which through some obscure #ifdefs does not eventually include any code
-// why...?
-#ifdef __clang__
-	#include</usr/include/fenv.h>
-#endif
-
-
 #include<iostream>
 #include<vector>
 #include<cstdlib>
@@ -20,7 +12,8 @@
 #include<boost/foreach.hpp>
 #include<boost/lexical_cast.hpp>
 #include<boost/python.hpp>
-#include<yade/extra/boost_python_len.hpp>
+#include<boost/python/object.hpp>
+#include<boost/version.hpp>
 #include<boost/math/distributions/normal.hpp>
 
 

=== modified file 'lib/triangulation/FlowBoundingSphere.hpp'
--- lib/triangulation/FlowBoundingSphere.hpp	2012-11-23 13:02:02 +0000
+++ lib/triangulation/FlowBoundingSphere.hpp	2013-05-03 16:45:52 +0000
@@ -1,5 +1,7 @@
 /*************************************************************************
-*  Copyright (C) 2010 by Emanuele Catalano <catalano@xxxxxxxxxxxxxxx>    *
+*  Copyright (C) 2009 by Emanuele Catalano <catalano@xxxxxxxxxxxxxxx>    *
+*  Copyright (C) 2009 by Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>     *
+*  Copyright (C) 2012 by Donia Marzougui <donia.marzougui@xxxxxxxxxxxxxxx>*
 *                                                                        *
 *  This program is free software; it is licensed under the terms of the  *
 *  GNU General Public License v2 or later. See file LICENSE for details. *
@@ -49,6 +51,7 @@
 		bool noCache;//flag for checking if cached values cell->unitForceVectors have been defined
 		bool computedOnce;//flag for checking if current triangulation has been computed at least once
 		bool pressureChanged;//are imposed pressures modified (on python side)? When it happens, we have to reApplyBoundaryConditions
+		int errorCode;
 		
 		//Handling imposed pressures/fluxes on elements in the form of {point,value} pairs, IPCells contains the cell handles corresponding to point
 		vector<pair<Point,Real> > imposedP;
@@ -76,14 +79,7 @@
 		vector <Finite_edges_iterator>  Edge_list;
 		vector <double> Edge_Surfaces;
 		vector <pair<int,int> > Edge_ids;
-		vector <Vector3r> Edge_force_point;
-		vector <Real> Edge_HydRad;
-		vector <Vector3r> Edge_normal;
-		vector <Real> Edge_surfaceDist;
 		vector <Real> edgeNormalLubF;
-		vector <Vector3r>Edge_centerDistVect;
-		vector <Real> Edge_centerDist;
-		vector <Real> Edge_meanRad;
 		vector <Vector3r> viscousShearForces;
 		vector <Vector3r> viscousShearTorques;
 		vector <Vector3r> normLubForce;
@@ -138,10 +134,10 @@
 
 		void GenerateVoxelFile ( );
 		
-		void ComputeEdgesSurfaces();
-		Vector3r ComputeViscousForce(Vector3r deltaV, int edge_id);
-		Real ComputeNormalLubricationForce(const Real& deltaNormV, const Real& dist, const int& edge_id, const Real& eps, const Real& stiffness, const Real& dt);
-		Vector3r ComputeShearLubricationForce(Vector3r deltaV,int edge_id, Real eps);
+		void computeEdgesSurfaces();
+		Vector3r computeViscousShearForce(const Vector3r& deltaV, const int& edge_id, const Real& Rh);
+		Real computeNormalLubricationForce(const Real& deltaNormV, const Real& dist, const int& edge_id, const Real& eps, const Real& stiffness, const Real& dt, const Real& meanRad);
+		Vector3r computeShearLubricationForce(const Vector3r& deltaShearV, const Real& dist, const int& edge_id, const Real& eps, const Real& centerDist, const Real& meanRad);
 
 		RTriangulation& Build_Triangulation ( Real x, Real y, Real z, Real radius, unsigned const id );
 

=== modified file 'lib/triangulation/FlowBoundingSphere.ipp'
--- lib/triangulation/FlowBoundingSphere.ipp	2012-11-26 10:51:33 +0000
+++ lib/triangulation/FlowBoundingSphere.ipp	2013-05-03 16:45:52 +0000
@@ -1,5 +1,7 @@
 /*************************************************************************
-*  Copyright (C) 2010 by Emanuele Catalano <catalano@xxxxxxxxxxxxxxx>    *
+*  Copyright (C) 2009 by Emanuele Catalano <catalano@xxxxxxxxxxxxxxx>    *
+*  Copyright (C) 2009 by Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>     *
+*  Copyright (C) 2012 by Donia Marzougui <donia.marzougui@xxxxxxxxxxxxxxx>*
 *                                                                        *
 *  This program is free software; it is licensed under the terms of the  *
 *  GNU General Public License v2 or later. See file LICENSE for details. *
@@ -94,6 +96,7 @@
 	minKdivKmean=0.0001;
 	maxKdivKmean=100.;
 	ompThreads=1;
+	errorCode=0;
 }
 
 template <class Tesselation> 
@@ -928,7 +931,7 @@
 	Vecteur x = B/sqrt(B.squared_length());
 	Vecteur C = cell->vertex(facetVertices[j][2])->point().point()-cell->vertex(facetVertices[j][0])->point().point();
 	Vecteur z = CGAL::cross_product(x,C);
-	z = z/sqrt(z.squared_length());
+// 	z = z/sqrt(z.squared_length());
 	Vecteur y = CGAL::cross_product(x,z);
 	y = y/sqrt(y.squared_length());
 
@@ -952,9 +955,12 @@
 
 	if ((pow(b,2)-4*a*c)<0){cout << "NEGATIVE DETERMINANT" << endl; }
 	double reff = (-b+sqrt(pow(b,2)-4*a*c))/(2*a);
-	if (reff<0 || reff==0) {cout << "reff1 = " << reff << endl; reff = (-b-sqrt(pow(b,2)-4*a*c))/(2*a); cout << endl << "reff2 = " << reff << endl;return reff;} else
-	return reff;
+	if (reff<0) return 0;//happens very rarely, with bounding spheres most probably
+	//if the facet involves one ore more bounding sphere, we return R with a minus sign
+	if (cell->vertex(facetVertices[j][2])->info().isFictious || cell->vertex(facetVertices[j][1])->info().isFictious || cell->vertex(facetVertices[j][2])->info().isFictious) return -reff;
+	else return reff;
 }
+
 template <class Tesselation> 
 double FlowBoundingSphere<Tesselation>::Compute_EquivalentRadius(Cell_handle cell, int j)
 {
@@ -1611,90 +1617,80 @@
 	cerr << "meanCmsVel "<<meanCmsVel/totCmsPoints<<" mean diff "<<diff/kk<<endl;
 }
 template <class Tesselation>
-void  FlowBoundingSphere<Tesselation>::ComputeEdgesSurfaces()
+void  FlowBoundingSphere<Tesselation>::computeEdgesSurfaces()
 {
   RTriangulation& Tri = T[currentTes].Triangulation();
-  Edge_normal.clear(); Edge_Surfaces.clear(); Edge_ids.clear(); Edge_HydRad.clear();
-  Edge_force_point.clear();Edge_centerDist.clear(); Edge_meanRad.clear();
-  Edge_surfaceDist.clear(); Edge_centerDistVect.clear();
+
+  //first, copy interacting pairs and normal lub forces form prev. triangulation in a sorted structure for initializing the new lub. Forces
+  vector<vector<pair<unsigned int,Real> > > lubPairs;
+  lubPairs.resize(Tri.number_of_vertices()+1);
+  for (unsigned int k=0; k<edgeNormalLubF.size(); k++)
+	lubPairs[min(Edge_ids[k].first,Edge_ids[k].second)].push_back(pair<int,Real> (max(Edge_ids[k].first,Edge_ids[k].second),edgeNormalLubF[k]));
+
+  //Now we reset the containers and initialize them
+  Edge_Surfaces.clear(); Edge_ids.clear(); edgeNormalLubF.clear();
   Finite_edges_iterator ed_it;
   for ( Finite_edges_iterator ed_it = Tri.finite_edges_begin(); ed_it!=Tri.finite_edges_end();ed_it++ )
   {
-    Real Rh;
     int hasFictious= (ed_it->first)->vertex(ed_it->second)->info().isFictious +  (ed_it->first)->vertex(ed_it->third)->info().isFictious;
-    if (hasFictious ==2) continue;
-    int id1 = (ed_it->first)->vertex(ed_it->second)->info().id();
-    int id2 = (ed_it->first)->vertex(ed_it->third)->info().id();
+    if (hasFictious==2) continue;
     double area = T[currentTes].ComputeVFacetArea(ed_it);
     Edge_Surfaces.push_back(area);
+    unsigned int id1 = (ed_it->first)->vertex(ed_it->second)->info().id();
+    unsigned int id2 = (ed_it->first)->vertex(ed_it->third)->info().id();
     Edge_ids.push_back(pair<int,int>(id1,id2));
-    double radius1 = sqrt((ed_it->first)->vertex(ed_it->second)->point().weight());
-    double radius2 = sqrt((ed_it->first)->vertex(ed_it->third)->point().weight());
-
-    Real surfaceDist; Real centerDist; Vecteur centerDistVect; Real meanRad; Vecteur point_force;Vecteur n;
-    if (!hasFictious){
-	centerDistVect=(ed_it->first)->vertex(ed_it->third)->point().point()- (ed_it->first)->vertex(ed_it->second)->point().point();
-	centerDist = sqrt(centerDistVect.squared_length());
-	meanRad = (radius1 + radius2)/2.;
-	surfaceDist = centerDist -radius2 -radius1;
-	n = centerDistVect / sqrt(centerDistVect.squared_length());
-	point_force = (centerDist/2. + (pow(radius1,2) - pow(radius2,2)) / (2.*centerDist))*n;
-	Rh = (radius1<radius2)? surfaceDist + 0.45 * radius1 : surfaceDist + 0.45 * radius2;
-    }
-    else if (hasFictious == 1){
-	bool v1fictious = (ed_it->first)->vertex(ed_it->second)->info().isFictious;
-	const Boundary& bnd = boundary(v1fictious? id1 : id2);
-	Vertex_handle vreal = v1fictious ? (ed_it->first)->vertex(ed_it->third) : (ed_it->first)->vertex(ed_it->second);
-	
-	centerDist = abs(vreal->point().point()[bnd.coordinate] -bnd.p[bnd.coordinate]);
-	centerDistVect = centerDist*bnd.normal;
-	meanRad = v1fictious ? radius2:radius1;
-	surfaceDist = centerDist- meanRad;
-	point_force = centerDistVect;
-	n = centerDistVect / sqrt(centerDistVect.squared_length());
-	Rh = surfaceDist + 0.45 * meanRad;
-    }
-    Edge_normal.push_back(Vector3r(n[0],n[1],n[2]));
-    Edge_HydRad.push_back(Rh);
-    edgeNormalLubF.push_back(0);
-    Edge_surfaceDist.push_back(surfaceDist);
-    Edge_centerDistVect.push_back(Vector3r(centerDistVect[0],centerDistVect[1],centerDistVect[2]));
-    Edge_centerDist.push_back(centerDist);
-    Edge_meanRad.push_back(meanRad);
-    Edge_force_point.push_back(Vector3r(point_force[0],point_force[1],point_force[2]));
-
-	
-//     if (DEBUG_OUT) cout<<"id1= "<<id1<<", id2= "<<id2<<", area= "<<area<<", R1= "<<radius1<<", R2= "<<radius2<<" x= "<<x<<", n= "<<n<<", Rh= "<<Rh<<endl;
+    
+    //For persistant edges, we must transfer the lub. force value from the older triangulation structure
+    if (id1>id2) swap(id1,id2);
+    unsigned int i=0;
+    //Look for the pair (id1,id2) in lubPairs
+    while (i<lubPairs[id1].size()) {
+		if (lubPairs[id1][i].first == id2) {
+			//it's found, we copy the lub force
+			edgeNormalLubF.push_back(lubPairs[id1][i].second);
+			break;}
+		++i;
+    }
+    // not found, we initialize with zero lub force
+    if (i==lubPairs[id1].size()) edgeNormalLubF.push_back(0);
   }
 }
+
 template <class Tesselation> 
-Vector3r FlowBoundingSphere<Tesselation>::ComputeViscousForce(Vector3r deltaV, int edge_id)
+Vector3r FlowBoundingSphere<Tesselation>::computeViscousShearForce(const Vector3r& deltaV, const int& edge_id, const Real& Rh)
 {
-    Vector3r tau = deltaV*VISCOSITY/Edge_HydRad[edge_id];
+    Vector3r tau = deltaV*VISCOSITY/Rh;
     return tau * Edge_Surfaces[edge_id];
 }
 
 template <class Tesselation> 
-Vector3r FlowBoundingSphere<Tesselation>::ComputeShearLubricationForce(Vector3r deltaV,int edge_id, Real eps)
+Vector3r FlowBoundingSphere<Tesselation>::computeShearLubricationForce(const Vector3r& deltaShearV, const Real& dist, const int& edge_id, const Real& eps, const Real& centerDist, const Real& meanRad )
 {
-    Vector3r viscLubF = 0.5 * Mathr::PI * VISCOSITY * (-2*Edge_meanRad[edge_id] + Edge_centerDist[edge_id]*log(Edge_centerDist[edge_id]/max(Edge_surfaceDist[edge_id],eps))) * deltaV;
+    Real d = max(dist,0.) + eps*meanRad;
+    Vector3r viscLubF = 0.5 * Mathr::PI * VISCOSITY * (-2*meanRad + centerDist*log(centerDist/d)) * deltaShearV;
     return viscLubF;
 }
 
 template <class Tesselation> 
-Real FlowBoundingSphere<Tesselation>::ComputeNormalLubricationForce(const Real& deltaNormV, const Real& dist, const int& edge_id, const Real& eps, const Real& stiffness, const Real& dt)
+Real FlowBoundingSphere<Tesselation>::computeNormalLubricationForce(const Real& deltaNormV, const Real& dist, const int& edge_id, const Real& eps, const Real& stiffness, const Real& dt, const Real& meanRad)
 {
 	//FIXME: here introduce elasticity
-	Real d = max(dist,0.) + eps*Edge_meanRad[edge_id];//account for grains roughness
+	Real d = max(dist,0.) + eps*meanRad;//account for grains roughness
 	if (stiffness>0) {
-		const Real k = stiffness*Edge_meanRad[edge_id];
-		const Real prevForce = edgeNormalLubF[edge_id] ? edgeNormalLubF[edge_id] : (6*Mathr::PI*pow(Edge_meanRad[edge_id],2)* VISCOSITY* deltaNormV)/d;
-		Real instantVisc = 6*Mathr::PI*pow(Edge_meanRad[edge_id],2)*VISCOSITY/(d-prevForce/k);
+		const Real k = stiffness*meanRad;
+		Real prevForce = edgeNormalLubF[edge_id];
+// 		Real prevForce = edgeNormalLubF[edge_id] ? edgeNormalLubF[edge_id] : (6*Mathr::PI*pow(meanRad,2)* VISCOSITY* deltaNormV)/d;
+// 		if (!edgeNormalLubF[edge_id]) for (int kk=0; kk<30; kk++) {
+// 			Real instantVisc = 6*Mathr::PI*pow(meanRad,2)*VISCOSITY/(d-prevForce/k);
+// 			prevForce = instantVisc*(deltaNormV + prevForce/(k*dt))/(1+instantVisc/(k*dt));
+// 			if ((kk==0 || kk==29) && deltaNormV!=0) cerr << "prevForce("<<kk<<") = "<< prevForce<<endl;
+// 		}
+		Real instantVisc = 1.5*Mathr::PI*pow(meanRad,2)*VISCOSITY/(d-prevForce/k);
 		Real normLubF = instantVisc*(deltaNormV + prevForce/(k*dt))/(1+instantVisc/(k*dt));
 		edgeNormalLubF[edge_id]=normLubF;
 		return normLubF;
 	} else {
-		Real normLubF = (6*Mathr::PI*pow(Edge_meanRad[edge_id],2)* VISCOSITY* deltaNormV)/d;
+		Real normLubF = (1.5*Mathr::PI*pow(meanRad,2)* VISCOSITY* deltaNormV)/d;
 		return normLubF;
 	}
 }

=== modified file 'lib/triangulation/PeriodicFlow.cpp'
--- lib/triangulation/PeriodicFlow.cpp	2012-11-23 13:02:02 +0000
+++ lib/triangulation/PeriodicFlow.cpp	2013-05-03 16:45:52 +0000
@@ -596,59 +596,49 @@
 	return Q1;
 }
 
-void  PeriodicFlow::ComputeEdgesSurfaces()
+void  PeriodicFlow::computeEdgesSurfaces()
 {
   RTriangulation& Tri = T[currentTes].Triangulation();
-  Edge_normal.clear(); Edge_Surfaces.clear(); Edge_ids.clear(); Edge_HydRad.clear();
-  Edge_force_point.clear();Edge_centerDist.clear();Edge_meanRad.clear();
-  Edge_surfaceDist.clear(); Edge_centerDistVect.clear();
+//first, copy interacting pairs and normal lub forces form prev. triangulation in a sorted structure for initializing the new lub. Forces
+  vector<vector<pair<unsigned int,Real> > > lubPairs;
+  lubPairs.resize(Tri.number_of_vertices()+1);
+  for (unsigned int k=0; k<edgeNormalLubF.size(); k++)
+	lubPairs[min(Edge_ids[k].first,Edge_ids[k].second)].push_back(pair<int,Real> (max(Edge_ids[k].first,Edge_ids[k].second),edgeNormalLubF[k]));
+
+  //Now we reset the containers and initialize them
+  
+  Edge_Surfaces.clear(); Edge_ids.clear(); edgeNormalLubF.clear();
   Finite_edges_iterator ed_it;
   for ( Finite_edges_iterator ed_it = Tri.finite_edges_begin(); ed_it!=Tri.finite_edges_end();ed_it++ )
   {
-    Real Rh; 
     int hasFictious= (ed_it->first)->vertex(ed_it->second)->info().isFictious +  (ed_it->first)->vertex(ed_it->third)->info().isFictious;
     if (hasFictious==2) continue;
-    else if (((ed_it->first)->vertex(ed_it->second)->info().isFictious) && ((ed_it->first)->vertex(ed_it->third)->info().isGhost)) continue;
-    else if (((ed_it->first)->vertex(ed_it->second)->info().isGhost) && ((ed_it->first)->vertex(ed_it->third)->info().isFictious)) continue;
-    else if (((ed_it->first)->vertex(ed_it->second)->info().isGhost) && ((ed_it->first)->vertex(ed_it->third)->info().isGhost)) continue;
-    int id1 = (ed_it->first)->vertex(ed_it->second)->info().id();
-    int id2 = (ed_it->first)->vertex(ed_it->third)->info().id();
+    if (((ed_it->first)->vertex(ed_it->second)->info().isGhost) && ((ed_it->first)->vertex(ed_it->third)->info().isGhost)) continue;
+    if (((ed_it->first)->vertex(ed_it->second)->info().isGhost) && ((ed_it->first)->vertex(ed_it->third)->info().isFictious)) continue;
+    if (((ed_it->first)->vertex(ed_it->second)->info().isFictious) && ((ed_it->first)->vertex(ed_it->third)->info().isGhost)) continue;
+
+    unsigned int id1 = (ed_it->first)->vertex(ed_it->second)->info().id();
+    unsigned int id2 = (ed_it->first)->vertex(ed_it->third)->info().id();
     double area = T[currentTes].ComputeVFacetArea(ed_it);
     Edge_Surfaces.push_back(area);
     Edge_ids.push_back(pair<int,int>(id1,id2));
-    double radius1 = sqrt((ed_it->first)->vertex(ed_it->second)->point().weight());
-    double radius2 = sqrt((ed_it->first)->vertex(ed_it->third)->point().weight());
 
-    Real surfaceDist; Real centerDist; Vecteur centerDistVect; Real meanRad; Vecteur point_force;Vecteur n;
-    if (!hasFictious){
-	centerDistVect=(ed_it->first)->vertex(ed_it->third)->point().point()- (ed_it->first)->vertex(ed_it->second)->point().point();
-	centerDist = sqrt(centerDistVect.squared_length());
-	meanRad = (radius1 + radius2)/2.;
-	surfaceDist = centerDist -radius2 -radius1;
-	n = centerDistVect / sqrt(centerDistVect.squared_length());
-	point_force = (centerDist/2. + (pow(radius1,2) - pow(radius2,2)) / (2.*centerDist))*n;
-	Rh = (radius1<radius2)? surfaceDist + 0.45 * radius1 : surfaceDist + 0.45 * radius2;
-    }
-    else if (hasFictious == 1){
-	centerDistVect = ((ed_it->first)->vertex(ed_it->second)->info().isFictious) ?((ed_it->first)->vertex(ed_it->third)->point().point()[boundary(id1).coordinate] - boundary(id1).p[boundary(id1).coordinate])*boundary(id1).normal : ((ed_it->first)->vertex(ed_it->second)->point().point()[boundary(id2).coordinate] - boundary(id2).p[boundary(id2).coordinate])*boundary(id2).normal;
-	centerDist = ((ed_it->first)->vertex(ed_it->second)->info().isFictious) ?abs((ed_it->first)->vertex(ed_it->third)->point().point()[boundary(id1).coordinate] - boundary(id1).p[boundary(id1).coordinate]) : abs((ed_it->first)->vertex(ed_it->second)->point().point()[boundary(id2).coordinate] - boundary(id2).p[boundary(id2).coordinate]);
-	surfaceDist = ((ed_it->first)->vertex(ed_it->second)->info().isFictious) ? centerDist -radius2 : centerDist -radius1;
-	meanRad = ((ed_it->first)->vertex(ed_it->second)->info().isFictious) ? radius2:radius1;
-	point_force = centerDistVect;
-	n = centerDistVect / sqrt(centerDistVect.squared_length());
-	Rh = ((ed_it->first)->vertex(ed_it->second)->info().isFictious) ? surfaceDist + 0.45 * radius2 : surfaceDist + 0.45 * radius1;
-    }
-    Edge_normal.push_back(Vector3r(n[0],n[1],n[2]));
-    Edge_HydRad.push_back(Rh);
-    Edge_surfaceDist.push_back(surfaceDist);
-    edgeNormalLubF.push_back(0);
-    Edge_centerDistVect.push_back(Vector3r(centerDistVect[0],centerDistVect[1],centerDistVect[2]));
-    Edge_centerDist.push_back(centerDist);
-    Edge_meanRad.push_back(meanRad);
-    Edge_force_point.push_back(Vector3r(point_force[0],point_force[1],point_force[2]));
+    //For persistant edges, we must transfer the lub. force value from the older triangulation structure
+    if (id1>id2) swap(id1,id2);
+    unsigned int i=0;
+    //Look for the pair (id1,id2) in lubPairs
+    while (i<lubPairs[id1].size()) {
+		if (lubPairs[id1][i].first == id2) {
+			//it's found, we copy the lub force
+			edgeNormalLubF.push_back(lubPairs[id1][i].second);
+			break;}
+		++i;
+    }
+    // not found, we initialize with zero lub force
+    if (i==lubPairs[id1].size()) edgeNormalLubF.push_back(0);
+//     edgeNormalLubF.push_back(0);
     
   }
-  if (DEBUG_OUT)cout << "size of Edge_ids "<< Edge_ids.size()<< ", size of area "<< Edge_Surfaces.size() << ", size of Rh "<< Edge_HydRad.size()<< ", size of normal "<<Edge_normal.size() << endl;
 }
 
 } //namespace CGT

=== modified file 'lib/triangulation/PeriodicFlow.hpp'
--- lib/triangulation/PeriodicFlow.hpp	2012-07-26 15:54:39 +0000
+++ lib/triangulation/PeriodicFlow.hpp	2012-12-03 08:19:32 +0000
@@ -26,7 +26,7 @@
 		void Compute_Permeability();
 		void GaussSeidel(Real dt=0);
 		void DisplayStatistics();
-		void ComputeEdgesSurfaces();
+		void computeEdgesSurfaces();
 		double boundaryFlux(unsigned int boundaryId);
 		#ifdef EIGENSPARSE_LIB
 		//Eigen's sparse matrix for forces computation

=== modified file 'lib/triangulation/def_types.h'
--- lib/triangulation/def_types.h	2012-11-26 10:51:33 +0000
+++ lib/triangulation/def_types.h	2013-02-07 18:12:42 +0000
@@ -76,7 +76,7 @@
 	inline Real& f (void) {return s;}
 	inline Real& v (void) {return vol;}
 	inline const unsigned int& id (void) const {return i;}
-	SimpleVertexInfo (void) {isFictious=false; s=0; i=0;}
+	SimpleVertexInfo (void) {isFictious=false; s=0; i=0; vol=-1;}
 	//virtual function that will be defined for all classes, allowing shared function (e.g. for display)
 	virtual bool isReal (void) {return !isFictious;}
 };

=== modified file 'pkg/common/Bo1_Facet_Aabb.cpp'
--- pkg/common/Bo1_Facet_Aabb.cpp	2010-11-12 08:03:16 +0000
+++ pkg/common/Bo1_Facet_Aabb.cpp	2013-03-07 18:28:01 +0000
@@ -26,16 +26,16 @@
 		for (int i=1;i<3;++i)
 		{
 			Vector3r v = O + facetAxisT * vertices[i];
-			aabb->min = aabb->min.cwise().min(v);
-			aabb->max = aabb->max.cwise().max(v);
+			aabb->min = aabb->min.cwiseMin(v);
+			aabb->max = aabb->max.cwiseMax(v);
 		}
 	} else {
 		Real inf=std::numeric_limits<Real>::infinity();
 		aabb->min=Vector3r(inf,inf,inf); aabb->max=Vector3r(-inf,-inf,-inf);
 		for(int i=0; i<3; i++){
 			Vector3r v=scene->cell->unshearPt(O+facetAxisT*vertices[i]);
-			aabb->min=aabb->min.cwise().min(v);
-			aabb->max=aabb->max.cwise().max(v);
+			aabb->min=aabb->min.cwiseMin(v);
+			aabb->max=aabb->max.cwiseMax(v);
 		}
 	}
 }

=== modified file 'pkg/common/Cylinder.cpp'
--- pkg/common/Cylinder.cpp	2012-10-09 09:09:02 +0000
+++ pkg/common/Cylinder.cpp	2013-03-06 20:47:43 +0000
@@ -490,7 +490,6 @@
 		else{	//else create the geometry.
 			if(!isNew) scm=YADE_PTR_CAST<ChCylGeom6D>(c->geom);
 			else { scm=shared_ptr<ChCylGeom6D>(new ChCylGeom6D()); c->geom=scm; }
-			scm->cylCyl=1;	//mark the geometry as contact between two different chainedCylinders : allows CohFrictPhys to compute the right contact parameters.
 			scm->relPos1=colinearVectors?0.5:k ; scm->relPos2=colinearVectors?0.5:m;
 			scm->fictiousState1.pos=A + k*a;
 			scm->fictiousState2.pos=B + m*b;
@@ -517,7 +516,6 @@
 		shared_ptr<ScGeom6D> scm;
 		if(!isNew) scm=YADE_PTR_CAST<ScGeom6D>(c->geom);
 		else { scm=shared_ptr<ScGeom6D>(new ScGeom6D()); c->geom=scm; }
-		scm->cylCyl=0;
 		Real length=(bchain2.pos-bchain1.pos).norm();
 		Vector3r segt =pChain2->pos-pChain1->pos;
 		if(isNew) {/*scm->normal=scm->prevNormal=segt/length;*/bs1->initLength=length;}
@@ -682,7 +680,7 @@
 	shearForce -= phys->ks*shearDisp;
 	Real maxFs = phys->normalForce.squaredNorm()*std::pow(phys->tangensOfFrictionAngle,2);
 
-	if (likely(!scene->trackEnergy)){//Update force but don't compute energy terms (see below))
+	if (!scene->trackEnergy){//Update force but don't compute energy terms (see below))
 		// PFC3d SlipModel, is using friction angle. CoulombCriterion
 		if( shearForce.squaredNorm() > maxFs ){
 			Real ratio = sqrt(maxFs) / shearForce.norm();

=== modified file 'pkg/common/ForceResetter.cpp'
--- pkg/common/ForceResetter.cpp	2010-11-24 22:42:15 +0000
+++ pkg/common/ForceResetter.cpp	2013-03-06 17:30:45 +0000
@@ -5,6 +5,6 @@
 
 void ForceResetter::action(){
 	scene->forces.reset(scene->iter);
-	if(unlikely(scene->trackEnergy)) scene->energy->resetResettables();
+	if(scene->trackEnergy) scene->energy->resetResettables();
 }
 

=== modified file 'pkg/common/Gl1_NormPhys.cpp'
--- pkg/common/Gl1_NormPhys.cpp	2011-03-24 21:38:33 +0000
+++ pkg/common/Gl1_NormPhys.cpp	2013-03-07 18:28:01 +0000
@@ -74,8 +74,8 @@
 		const Vector3r& dispScale=scene->renderer ? scene->renderer->dispScale : Vector3r::Ones(); 
 		if(dispScale!=Vector3r::Ones()){
 			// move p1 and p2 by the same amounts as particles themselves would be moved
-			p1+=dispScale.cwise()*Vector3r(b1->state->pos-b1->state->refPos);
-			p2+=dispScale.cwise()*Vector3r(b2->state->pos-b2->state->refPos);
+			p1+=dispScale.cwiseProduct(Vector3r(b1->state->pos-b1->state->refPos));
+			p2+=dispScale.cwiseProduct(Vector3r(b2->state->pos-b2->state->refPos));
 		}
 		Vector3r relPos=p2-p1;
 		Real dist=relPos.norm(); //max(geom->refR1,0.)+max(geom->refR2,0.);

=== modified file 'pkg/common/GravityEngines.cpp'
--- pkg/common/GravityEngines.cpp	2012-01-30 10:42:13 +0000
+++ pkg/common/GravityEngines.cpp	2013-03-06 17:30:45 +0000
@@ -17,7 +17,7 @@
 
 void GravityEngine::action(){
 	if (warnOnce) {warnOnce=false; LOG_ERROR("GravityEngine is deprecated, consider using Newton::gravity instead (unless gravitational energy has to be tracked - not implemented with the newton attribute).")}
-	const bool trackEnergy(unlikely(scene->trackEnergy));
+	const bool trackEnergy(scene->trackEnergy);
 	const Real dt(scene->dt);
 	YADE_PARALLEL_FOREACH_BODY_BEGIN(const shared_ptr<Body>& b, scene->bodies){
 		// skip clumps, only apply forces on their constituents

=== modified file 'pkg/common/Grid.cpp'
--- pkg/common/Grid.cpp	2012-11-22 14:34:48 +0000
+++ pkg/common/Grid.cpp	2013-04-30 09:52:44 +0000
@@ -77,7 +77,6 @@
 						const shared_ptr<Interaction>& c)
 {	// Useful variables :
 	const State*    sphereSt  = YADE_CAST<const State*>(&state1);
-	//const State*    gridCoSt  = YADE_CAST<const State*>(&state2);
 	Sphere*         sphere    = YADE_CAST<Sphere*>(cm1.get());
 	GridConnection* gridCo    = YADE_CAST<GridConnection*>(cm2.get());
 	GridNode*       gridNo1   = YADE_CAST<GridNode*>(gridCo->node1->shape.get());
@@ -98,10 +97,23 @@
 		if(abs(branchN[i])<1e-14) branchN[i]=0.0;
 	}
 	Real relPos = branch.dot(segt)/(len*len);
-	if(scm->isDuplicate==2 && scm->trueInt!=c->id2)return true;	//the contact will be deleted into the Law.
+	if(scm->isDuplicate==2 && scm->trueInt!=c->id2)return true;	//the contact will be deleted into the Law, no need to compute here.
 	scm->isDuplicate=0;
 	scm->trueInt=-1;
 	
+	/*
+	The 4 conditions below are used to avoid double contact between a sphere and two cylinders, and to follow contact properties when the sphere is sliding along different consecutive GridConnections.
+	If none of these conditions are satisfied, the classic contact will be done at the bottom of the Ig2. Else the contact may be copied (if sliding), deleted (if just copied and/or duplicated) and the return statement may be used to abort the Ig2.
+	
+	The first and the second conditions detect if a sphere's projections is outside the connection. So the contact :
+	 - have to be created if the projection is outside all neighbours and not already created.
+	 - have to be ignored if the projection is inside at least one neighbour.
+	 - if the contact is sliding out to another connection (detected via isNew), mark it as duplicated (it will be ignored by the law and imported (copied) by the new contact).
+	 
+	 The third and the fourth conditions detect if a sphere's projections is inside the connection. So if the contact is new and :
+	  - is before the middle of the connection, we search an old contact that may have slided from one of the previous connections. If we find one, we import it here.
+	  - is after the middle of the connection, we search an old contact that may have slided from one of the following connections. If we find one, we import it here.
+	 */
 	if(relPos<=0){	// if the sphere projection is BEFORE the segment ...
 		if(gridNo1->ConnList.size()>1){//	if the node is not an extremity of the Grid (only one connection)
 			for(int unsigned i=0;i<gridNo1->ConnList.size();i++){	// ... loop on all the Connections of the same Node ...
@@ -180,6 +192,7 @@
 						scm=YADE_PTR_CAST<ScGridCoGeom>(intr->geom);
 						c->geom=scm;
 						c->phys=intr->phys;
+						c->iterMadeReal=intr->iterMadeReal;
 						scm->trueInt=c->id2;
 						scm->isDuplicate=2;	//command the old contact deletion.
 						isNew=0;
@@ -209,6 +222,7 @@
 						scm=YADE_PTR_CAST<ScGridCoGeom>(intr->geom);
 						c->geom=scm;
 						c->phys=intr->phys;
+						c->iterMadeReal=intr->iterMadeReal;
 						scm->trueInt=c->id2;
 						scm->isDuplicate=2;	//command the old contact deletion.
 						isNew=0;
@@ -264,7 +278,6 @@
 //!			O/
 void Law2_ScGridCoGeom_FrictPhys_CundallStrack::go(shared_ptr<IGeom>& ig, shared_ptr<IPhys>& ip, Interaction* contact){
 	int id1 = contact->getId1(), id2 = contact->getId2();
-
 	ScGridCoGeom* geom= static_cast<ScGridCoGeom*>(ig.get());
 	FrictPhys* phys = static_cast<FrictPhys*>(ip.get());
 	if(geom->penetrationDepth <0){
@@ -291,7 +304,7 @@
 	shearForce -= phys->ks*shearDisp;
 	Real maxFs = phys->normalForce.squaredNorm()*std::pow(phys->tangensOfFrictionAngle,2);
 
-	if (likely(!scene->trackEnergy)){//Update force but don't compute energy terms (see below))
+	if (!scene->trackEnergy){//Update force but don't compute energy terms (see below))
 		// PFC3d SlipModel, is using friction angle. CoulombCriterion
 		if( shearForce.squaredNorm() > maxFs ){
 			Real ratio = sqrt(maxFs) / shearForce.norm();
@@ -309,28 +322,86 @@
 		// compute elastic energy as well
 		scene->energy->add(0.5*(phys->normalForce.squaredNorm()/phys->kn+phys->shearForce.squaredNorm()/phys->ks),"elastPotential",elastPotentialIx,/*reset at every timestep*/true);
 	}
-// 	if (!scene->isPeriodic) {
+	Vector3r force = -phys->normalForce-shearForce;
+	scene->forces.addForce(id1,force);
+	scene->forces.addTorque(id1,(geom->radius1-0.5*geom->penetrationDepth)* geom->normal.cross(force));
+	Vector3r twist = (geom->radius2-0.5*geom->penetrationDepth)* geom->normal.cross(force);
+	scene->forces.addForce(geom->id3,(geom->relPos-1)*force);
+	scene->forces.addTorque(geom->id3,(1-geom->relPos)*twist);
+	scene->forces.addForce(geom->id4,(-geom->relPos)*force);
+	scene->forces.addTorque(geom->id4,geom->relPos*twist);
+}
+YADE_PLUGIN((Law2_ScGridCoGeom_FrictPhys_CundallStrack));
+
+
+void Law2_ScGridCoGeom_CohFrictPhys_CundallStrack::go(shared_ptr<IGeom>& ig, shared_ptr<IPhys>& ip, Interaction* contact){
+	const int &id1 = contact->getId1();
+	const int &id2 = contact->getId2();
+	ScGridCoGeom* geom  = YADE_CAST<ScGridCoGeom*> (ig.get());
+	CohFrictPhys* phys = YADE_CAST<CohFrictPhys*> (ip.get());
+	
+	if (geom->isDuplicate) {
+		if (id2!=geom->trueInt) {
+			//cerr<<"skip duplicate "<<id1<<" "<<id2<<endl;
+			if (geom->isDuplicate==2) {
+				//cerr<<"erase duplicate "<<id1<<" "<<id2<<endl;
+				scene->interactions->requestErase(contact);
+			}
+			return;
+		}
+	}
+	
+	Vector3r& shearForce    = phys->shearForce;
+	if (contact->isFresh(scene) && geom->isDuplicate!=2) shearForce = Vector3r::Zero();
+	Real un     = geom->penetrationDepth;
+	Real Fn    = phys->kn*(un-phys->unp);
+	
+	if (phys->fragile && (-Fn)> phys->normalAdhesion) {
+		// BREAK due to tension
+		scene->interactions->requestErase(contact); return;
+	} else {
+		if ((-Fn)> phys->normalAdhesion) {//normal plasticity
+			Fn=-phys->normalAdhesion;
+			phys->unp = un+phys->normalAdhesion/phys->kn;
+			if (phys->unpMax && phys->unp<phys->unpMax)
+				scene->interactions->requestErase(contact); return;
+		}
+		phys->normalForce = Fn*geom->normal;
+		Vector3r& shearForce = geom->rotate(phys->shearForce);
+		const Vector3r& dus = geom->shearIncrement();
+
+		//Linear elasticity giving "trial" shear force
+		shearForce -= phys->ks*dus;
+
+		Real Fs = phys->shearForce.norm();
+		Real maxFs = phys->shearAdhesion;
+		if (!phys->cohesionDisablesFriction || maxFs==0)
+			maxFs += Fn*phys->tangensOfFrictionAngle;
+		maxFs = std::max((Real) 0, maxFs);
+		if (Fs  > maxFs) {//Plasticity condition on shear force
+			if (phys->fragile && !phys->cohesionBroken) {
+				phys->SetBreakingState();
+				maxFs = max((Real) 0, Fn*phys->tangensOfFrictionAngle);
+			}
+			maxFs = maxFs / Fs;
+			Vector3r trialForce=shearForce;
+			shearForce *= maxFs;
+			if (scene->trackEnergy){
+				Real dissip=((1/phys->ks)*(trialForce-shearForce))/*plastic disp*/ .dot(shearForce)/*active force*/;
+				if(dissip>0) scene->energy->add(dissip,"plastDissip",plastDissipIx,/*reset*/false);}
+			if (Fn<0)  phys->normalForce = Vector3r::Zero();//Vector3r::Zero()
+		}
 		Vector3r force = -phys->normalForce-shearForce;
 		scene->forces.addForce(id1,force);
 		scene->forces.addTorque(id1,(geom->radius1-0.5*geom->penetrationDepth)* geom->normal.cross(force));
-		//FIXME : include moment due to axis-contact distance in forces on node
 		Vector3r twist = (geom->radius2-0.5*geom->penetrationDepth)* geom->normal.cross(force);
 		scene->forces.addForce(geom->id3,(geom->relPos-1)*force);
 		scene->forces.addTorque(geom->id3,(1-geom->relPos)*twist);
 		scene->forces.addForce(geom->id4,(-geom->relPos)*force);
 		scene->forces.addTorque(geom->id4,geom->relPos*twist);
-// 	}
-// // 		applyForceAtContactPoint(-phys->normalForce-shearForce, geom->contactPoint, id1, de1->se3.position, id2, de2->se3.position);
-// 	else {//FIXME : periodicity not implemented here :
-// 		Vector3r force = -phys->normalForce-shearForce;
-// 		scene->forces.addForce(id1,force);
-// 		scene->forces.addForce(id2,-force);
-// 		scene->forces.addTorque(id1,(geom->radius1-0.5*geom->penetrationDepth)* geom->normal.cross(force));
-// 		scene->forces.addTorque(id2,(geom->radius2-0.5*geom->penetrationDepth)* geom->normal.cross(force));
-// 	}
+	}
 }
-YADE_PLUGIN((Law2_ScGridCoGeom_FrictPhys_CundallStrack));
-
+YADE_PLUGIN((Law2_ScGridCoGeom_CohFrictPhys_CundallStrack));
 
 //!##################	Bounds   #####################
 
@@ -381,7 +452,7 @@
 	Real length=GC->getLength();
 	const shared_ptr<Interaction> intr = scene->interactions->find((int)GC->node1->getId(),(int)GC->node2->getId());
 	Vector3r segt = GC->node2->state->pos - GC->node1->state->pos;
-	if (scene->isPeriodic) segt+=scene->cell->intrShiftPos(intr->cellDist);
+	if (scene->isPeriodic && intr) segt+=scene->cell->intrShiftPos(intr->cellDist);
 	//glMaterialv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, Vector3f(cm->color[0],cm->color[1],cm->color[2]));
 
 	glColor3v(cm->color);
@@ -396,7 +467,7 @@
 	return;
 }
 
-void Gl1_GridConnection::drawCylinder(bool wire, Real radius, Real length, const Quaternionr& shift) const
+void Gl1_GridConnection::drawCylinder(bool wire, Real radius, Real length, const Quaternionr& shift)
 {
    glPushMatrix();
    GLUquadricObj *quadObj = gluNewQuadric();
@@ -416,4 +487,4 @@
    glPopMatrix();
 }
 YADE_PLUGIN((Gl1_GridConnection));
-#endif
\ No newline at end of file
+#endif

=== modified file 'pkg/common/Grid.hpp'
--- pkg/common/Grid.hpp	2012-11-22 14:34:48 +0000
+++ pkg/common/Grid.hpp	2013-05-14 21:24:11 +0000
@@ -5,13 +5,29 @@
 *  GNU General Public License v2 or later. See file LICENSE for details. *
 *************************************************************************/
 
+/* TABLE OF CONTENT, and the minimum you need to understand.
+- 2 new shapes for grids : GridNode (vertices) and GridConnection (edges)
+- 2 new contact geometries :
+    * GridNodeGeom6D to handle GridNode-GridNode contacts (the internal behaviour of the grid)
+    * ScGridCoGeom to handle Sphere-GridConnection contacts (the interaction between the grid and an external sphere)
+        Note : the Sphere-Grid contacts are always handled by the GridConnections, but the forces are applied on the related GridNodes.
+        Note : there is no contact between two GridConnections, they must be linked with GridNodes.
+- The 2 related Ig2 :
+    * Ig2_GridNode_GridNode_GridNodeGeom6D (doing almost the same than Ig2_Sphere_Sphere_ScGeom6D)
+    * Ig2_Sphere_GridConnection_ScGridCoGeom (the biggest part of the code, it handles contact detection and history when a sphere is sliding on the grid over consecutive GridConnections)
+- The Law2_ScGridCoGeom_FrictPhys_CundallStrack who handles the elastic frictional Sphere-GridConnection contact. The GridNode-GridNode law is Law2_ScGeom6D_CohFrictPhys_CohesionMoment by inheritance.
+*/
+
+
+
 #pragma once
 #include "Sphere.hpp"
-#include<yade/pkg/dem/FrictPhys.hpp>
+#include <yade/pkg/dem/FrictPhys.hpp>
+#include <yade/pkg/dem/CohFrictPhys.hpp>
 #include <yade/pkg/dem/ScGeom.hpp>
 #include <yade/core/Body.hpp>
-#include<yade/pkg/common/Dispatching.hpp>
-#include<yade/pkg/dem/Ig2_Sphere_Sphere_ScGeom.hpp>
+#include <yade/pkg/common/Dispatching.hpp>
+#include <yade/pkg/dem/Ig2_Sphere_Sphere_ScGeom.hpp>
 #ifdef YADE_OPENGL
 	#include<yade/pkg/common/GLDrawFunctors.hpp>
 #endif
@@ -25,13 +41,13 @@
 		virtual ~GridConnection();
 		Real getLength();
 		Vector3r getSegment();
-		YADE_CLASS_BASE_DOC_ATTRS_CTOR(GridConnection,Sphere,"GridConnection shape. Component of a grid designed to link two :yref:`GridNodes<GridNode>`. It's highly recommanded to use utils.gridConnection(...) to generate correct :yref:`GridConnections<GridConnection>`.",
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR(GridConnection,Sphere,"GridConnection shape. Component of a grid designed to link two :yref:`GridNodes<GridNode>`. It's highly recommended to use utils.gridConnection(...) to generate correct :yref:`GridConnections<GridConnection>`.",
 		((shared_ptr<Body> , node1 , ,,"First :yref:`Body` the GridConnection is connected to."))
 		((shared_ptr<Body> , node2 , ,,"Second :yref:`Body` the GridConnection is connected to."))
 		((bool, periodic, false,,"true if two nodes from different periods are connected."))
-		((Vector3i , cellDist , (0,0,0),,))
-		,createIndex();/*ctor*/
-		);
+		((Vector3i , cellDist , Vector3i(0,0,0),,"missing doc :(")),
+		createIndex(); /*ctor*/
+	);
 	REGISTER_CLASS_INDEX(GridConnection,Sphere);
 };
 REGISTER_SERIALIZABLE(GridConnection);
@@ -41,7 +57,7 @@
 	public:
 		virtual ~GridNode();
 		void addConnection(shared_ptr<Body> GC);
-	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(GridNode,Sphere,"GridNode shape, component of a grid.\nTo create a Grid, place the nodes first, they will define the spacial discretisation of it. It's highly recommanded to use utils.gridNode(...) to generate correct :yref:`GridNodes<GridNode>`. Note that the GridNodes should only be in an Interaction with other GridNodes. The Sphere-Grid contact is only handled by the :yref:`GridConnections<GridConnection>`.",
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(GridNode,Sphere,"GridNode shape, component of a grid.\nTo create a Grid, place the nodes first, they will define the spacial discretisation of it. It's highly recommended to use utils.gridNode(...) to generate correct :yref:`GridNodes<GridNode>`. Note that the GridNodes should only be in an Interaction with other GridNodes. The Sphere-Grid contact is only handled by the :yref:`GridConnections<GridConnection>`.",
 		((vector<shared_ptr<Body> >,ConnList,,,"List of :yref:`GridConnections<GridConnection>` the GridNode is connected to.")),
 		/*ctor*/
 		createIndex();,
@@ -50,7 +66,6 @@
 	);
 	REGISTER_CLASS_INDEX(GridNode,Sphere);
 };
-
 REGISTER_SERIALIZABLE(GridNode);
 
 
@@ -60,9 +75,8 @@
 class GridNodeGeom6D: public ScGeom6D {
 	public:
 		virtual ~GridNodeGeom6D();
-		YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(GridNodeGeom6D,ScGeom6D,"Geometry of a :yref:`GridNode`-:yref:`GridNode` contact. Inherits almost everything from :yref:`ScGeom6D`.",
-		((shared_ptr<Body>, connectionBody,,,"Reference to the :yref:`GridNode` :yref:`Body` who is linking the two :yref:`GridNodes<GridNode>`."))
-		,
+	YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(GridNodeGeom6D,ScGeom6D,"Geometry of a :yref:`GridNode`-:yref:`GridNode` contact. Inherits almost everything from :yref:`ScGeom6D`.",
+		((shared_ptr<Body>, connectionBody,,,"Reference to the :yref:`GridNode` :yref:`Body` who is linking the two :yref:`GridNodes<GridNode>`.")),
 		/* extra initializers */,
 		/* ctor */ createIndex();,
 		/* py */
@@ -72,20 +86,20 @@
 REGISTER_SERIALIZABLE(GridNodeGeom6D);
 
 //!			O/
-class ScGridCoGeom: public ScGeom {
-public:
-    /// Emulate a sphere whose position is the projection of sphere's center on cylinder sphere, and with motion linearly interpolated between nodes
-    State fictiousState;
-    virtual ~ScGridCoGeom ();
-    YADE_CLASS_BASE_DOC_ATTRS_CTOR(ScGridCoGeom,ScGeom,"Geometry of a :yref:`GridConnection`-:yref:`Sphere` contact.",
-                                   ((int,isDuplicate,0,,"this flag is turned true (1) automatically if the contact is shared between two Connections. A duplicated interaction will be skipped once by the constitutive law, so that only one contact at a time is effective. If isDuplicate=2, it means one of the two duplicates has no longer geometric interaction, and should be erased by the constitutive laws."))
-                                   ((int,trueInt,-1,,"Defines the body id of the :yref:`GridConnection` where the contact is real, when :yref:`ScGridCoGeom::isDuplicate`>0."))
-                                   ((int,id3,0,,"id of the first :yref:`GridNode`. |yupdate|"))
-                                   ((int,id4,0,,"id of the second :yref:`GridNode`. |yupdate|"))
-                                   ((Real,relPos,0,,"position of the contact on the connection (0: node-, 1:node+) |yupdate|")),
-                                   createIndex(); /*ctor*/
-                                  );
-    REGISTER_CLASS_INDEX(ScGridCoGeom,ScGeom);
+class ScGridCoGeom: public ScGeom6D {
+	public:
+		/// Emulate a sphere whose position is the projection of sphere's center on cylinder sphere, and with motion linearly interpolated between nodes
+		State fictiousState;
+		virtual ~ScGridCoGeom ();
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR(ScGridCoGeom,ScGeom6D,"Geometry of a :yref:`GridConnection`-:yref:`Sphere` contact.",
+		((int,isDuplicate,0,,"this flag is turned true (1) automatically if the contact is shared between two Connections. A duplicated interaction will be skipped once by the constitutive law, so that only one contact at a time is effective. If isDuplicate=2, it means one of the two duplicates has no longer geometric interaction, and should be erased by the constitutive laws."))
+		((int,trueInt,-1,,"Defines the body id of the :yref:`GridConnection` where the contact is real, when :yref:`ScGridCoGeom::isDuplicate`>0."))
+		((int,id3,0,,"id of the first :yref:`GridNode`. |yupdate|"))
+		((int,id4,0,,"id of the second :yref:`GridNode`. |yupdate|"))
+		((Real,relPos,0,,"position of the contact on the connection (0: node-, 1:node+) |yupdate|")),
+		createIndex(); /*ctor*/
+	);
+	REGISTER_CLASS_INDEX(ScGridCoGeom,ScGeom6D);
 };
 REGISTER_SERIALIZABLE(ScGridCoGeom);
 
@@ -96,11 +110,9 @@
 	public:
 		virtual bool go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
 		virtual bool goReverse(	const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
-
-		YADE_CLASS_BASE_DOC_ATTRS(Ig2_GridNode_GridNode_GridNodeGeom6D,Ig2_Sphere_Sphere_ScGeom,"Create/update a :yref:`GridNodeGeom6D` instance representing the geometry of a contact point between two :yref:`GridNode<GridNode>`, including relative rotations.",
+	YADE_CLASS_BASE_DOC_ATTRS(Ig2_GridNode_GridNode_GridNodeGeom6D,Ig2_Sphere_Sphere_ScGeom,"Create/update a :yref:`GridNodeGeom6D` instance representing the geometry of a contact point between two :yref:`GridNode<GridNode>`, including relative rotations.",
 		((bool,updateRotations,true,,"Precompute relative rotations. Turning this false can speed up simulations when rotations are not needed in constitutive laws (e.g. when spheres are compressed without cohesion and moment in early stage of a triaxial test), but is not foolproof. Change this value only if you know what you are doing."))
-		((bool,creep,false,,"Substract rotational creep from relative rotation. The rotational creep :yref:`ScGeom6D::twistCreep` is a quaternion and has to be updated inside a constitutive law, see for instance :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`."
-		))
+		((bool,creep,false,,"Substract rotational creep from relative rotation. The rotational creep :yref:`ScGeom6D::twistCreep` is a quaternion and has to be updated inside a constitutive law, see for instance :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`."))
 	);
 	FUNCTOR2D(GridNode,GridNode);
 	// needed for the dispatcher, even if it is symmetric
@@ -113,8 +125,7 @@
 	public:
 		virtual bool go(const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
 		virtual bool goReverse(	const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c);
-
-		YADE_CLASS_BASE_DOC_ATTRS(Ig2_Sphere_GridConnection_ScGridCoGeom,IGeomFunctor,"Create/update a :yref:`ScGridCoGeom6D` instance representing the geometry of a contact point between a :yref:`GricConnection` and a :yref:`Sphere` including relative rotations.",
+	YADE_CLASS_BASE_DOC_ATTRS(Ig2_Sphere_GridConnection_ScGridCoGeom,IGeomFunctor,"Create/update a :yref:`ScGridCoGeom6D` instance representing the geometry of a contact point between a :yref:`GricConnection` and a :yref:`Sphere` including relative rotations.",
 		((Real,interactionDetectionFactor,1,,"Enlarge both radii by this factor (if >1), to permit creation of distant interactions."))
 	);
 	FUNCTOR2D(Sphere,GridConnection);
@@ -129,9 +140,8 @@
 class Law2_ScGridCoGeom_FrictPhys_CundallStrack: public LawFunctor{
 	public:
 		virtual void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I);
-		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGridCoGeom_FrictPhys_CundallStrack,LawFunctor,"Law between a frictional :yref:`GridConnection` and a frictional :yref:`Sphere`. Almost the same than :yref:`Law2_ScGeom_FrictPhys_CundallStrack`, but the force is divided and applied on the two :yref:`GridNodes<GridNode>` only.",
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGridCoGeom_FrictPhys_CundallStrack,LawFunctor,"Law between a frictional :yref:`GridConnection` and a frictional :yref:`Sphere`. Almost the same than :yref:`Law2_ScGeom_FrictPhys_CundallStrack`, but the force is divided and applied on the two :yref:`GridNodes<GridNode>` only.",
 		((bool,neverErase,false,,"Keep interactions even if particles go away from each other (only in case another constitutive law is in the scene, e.g. :yref:`Law2_ScGeom_CapillaryPhys_Capillarity`)"))
-		((bool,traceEnergy,false,Attr::hidden,"Define the total energy dissipated in plastic slips at all contacts."))
 		((int,plastDissipIx,-1,(Attr::hidden|Attr::noSave),"Index for plastic dissipation (with O.trackEnergy)"))
 		((int,elastPotentialIx,-1,(Attr::hidden|Attr::noSave),"Index for elastic potential energy (with O.trackEnergy)"))
 		,,
@@ -140,6 +150,17 @@
 };
 REGISTER_SERIALIZABLE(Law2_ScGridCoGeom_FrictPhys_CundallStrack);
 
+class Law2_ScGridCoGeom_CohFrictPhys_CundallStrack: public LawFunctor{
+	public:
+		virtual void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I);
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGridCoGeom_CohFrictPhys_CundallStrack,LawFunctor,"Law between a cohesive frictional :yref:`GridConnection` and a cohesive frictional :yref:`Sphere`. Almost the same than :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`, but THE ROTATIONAL MOMENTS ARE NOT COMPUTED.",
+		((bool,neverErase,false,,"Keep interactions even if particles go away from each other (only in case another constitutive law is in the scene, e.g. :yref:`Law2_ScGeom_CapillaryPhys_Capillarity`)"))
+		((int,plastDissipIx,-1,(Attr::hidden|Attr::noSave),"Index for plastic dissipation (with O.trackEnergy)"))
+		,,
+	);
+	FUNCTOR2D(ScGridCoGeom,CohFrictPhys);
+};
+REGISTER_SERIALIZABLE(Law2_ScGridCoGeom_CohFrictPhys_CundallStrack);
 
 
 //!##################	Bounds   #####################
@@ -161,7 +182,7 @@
 	private:
 		//static int glCylinderList;
 		//void subdivideTriangle(Vector3r& v1,Vector3r& v2,Vector3r& v3, int depth);
-		void drawCylinder(bool wire, Real radius, Real length, const Quaternionr& shift=Quaternionr::Identity()) const;
+		void drawCylinder(bool wire, Real radius, Real length, const Quaternionr& shift=Quaternionr::Identity());
 		//void initGlLists(void);
 	public:
 		virtual void go(const shared_ptr<Shape>&, const shared_ptr<State>&,bool,const GLViewInfo&);
@@ -169,8 +190,8 @@
 	YADE_CLASS_BASE_DOC_STATICATTRS(Gl1_GridConnection,GlShapeFunctor,"Renders :yref:`Cylinder` object",
 		((bool,wire,false,,"Only show wireframe (controlled by ``glutSlices`` and ``glutStacks``."))
 		((bool,glutNormalize,true,,"Fix normals for non-wire rendering"))
-		((int,glutSlices,8,,"Number of sphere slices."))
-		((int,glutStacks,4,,"Number of sphere stacks."))
+		((int,glutSlices,8,,"Number of cylinder slices."))
+		((int,glutStacks,4,,"Number of cylinder stacks."))
 	);
 	RENDERS(GridConnection);
 };

=== modified file 'pkg/common/InsertionSortCollider.cpp'
--- pkg/common/InsertionSortCollider.cpp	2012-06-12 16:13:46 +0000
+++ pkg/common/InsertionSortCollider.cpp	2013-03-06 17:30:45 +0000
@@ -44,7 +44,7 @@
 			// also, do not collide body with itself; it sometimes happens for facets aligned perpendicular to an axis, for reasons that are not very clear
 			// see https://bugs.launchpad.net/yade/+bug/669095
 			// skip bounds with same isMin flags, since inversion doesn't imply anything in that case  
-			if(isMin && !v[j].flags.isMin && likely(doCollide && viInitBB && v[j].flags.hasBB && (viInit.id!=v[j].id))) {
+			if(isMin && !v[j].flags.isMin && doCollide && viInitBB && v[j].flags.hasBB && (viInit.id!=v[j].id)) {
 				/*if (isMin)*/ handleBoundInversion(viInit.id,v[j].id,interactions,scene);
 // 				else handleBoundSplit(viInit.id,v[j].id,interactions,scene);
 			}
@@ -64,7 +64,7 @@
 		if (!it->flags.isMin || !it->flags.hasBB) continue;
 		int offset = 3*it->id;
 		const shared_ptr<Body>& b=Body::byId(it->id,scene);
-		if(unlikely(!b || !b->bound)) continue;
+		if(!b || !b->bound) continue;
 		const Real& sweepLength = b->bound->sweepLength;
 		Vector3r disp = b->state->pos - b->bound->refPos;
 		if (!(maxima[offset]-sweepLength+disp[0] < bv.min[0] ||
@@ -200,7 +200,7 @@
 				VecBounds& BBj=BB[j];
 				const Body::id_t id=BBj[i].id;
 				const shared_ptr<Body>& b=Body::byId(id,scene);
-				if(likely(b)){
+				if(b){
 					const shared_ptr<Bound>& bv=b->bound;
 					// coordinate is min/max if has bounding volume, otherwise both are the position. Add periodic shift so that we are inside the cell
 					// watch out for the parentheses around ?: within ?: (there was unwanted conversion of the Reals to bools!)
@@ -218,9 +218,9 @@
 	BOOST_STATIC_ASSERT(sizeof(Vector3r)==3*sizeof(Real));
 	for(Body::id_t id=0; id<nBodies; id++){
 		const shared_ptr<Body>& b=Body::byId(id,scene);
-		if(likely(b)){
+		if(b){
 			const shared_ptr<Bound>& bv=b->bound;
-			if(likely(bv)) { memcpy(&minima[3*id],&bv->min,3*sizeof(Real)); memcpy(&maxima[3*id],&bv->max,3*sizeof(Real)); } // ⇐ faster than 6 assignments 
+			if(bv) { memcpy(&minima[3*id],&bv->min,3*sizeof(Real)); memcpy(&maxima[3*id],&bv->max,3*sizeof(Real)); } // ⇐ faster than 6 assignments 
 			else{ const Vector3r& pos=b->state->pos; memcpy(&minima[3*id],&pos,3*sizeof(Real)); memcpy(&maxima[3*id],&pos,3*sizeof(Real)); }
 		} else { memset(&minima[3*id],0,3*sizeof(Real)); memset(&maxima[3*id],0,3*sizeof(Real)); }
 	}
@@ -259,7 +259,7 @@
 				for(long i=0; i<2*nBodies; i++){
 					// start from the lower bound (i.e. skipping upper bounds)
 					// skip bodies without bbox, because they don't collide
-					if(unlikely(!(V[i].flags.isMin && V[i].flags.hasBB))) continue;
+					if(!(V[i].flags.isMin && V[i].flags.hasBB)) continue;
 					const Body::id_t& iid=V[i].id;
 					// go up until we meet the upper bound
 					for(long j=i+1; /* handle case 2. of swapped min/max */ j<2*nBodies && V[j].id!=iid; j++){
@@ -273,7 +273,7 @@
 				}
 			} else { // periodic case: see comments above
 				for(long i=0; i<2*nBodies; i++){
-					if(unlikely(!(V[i].flags.isMin && V[i].flags.hasBB))) continue;
+					if(!(V[i].flags.isMin && V[i].flags.hasBB)) continue;
 					const Body::id_t& iid=V[i].id;
 					long cnt=0;
 					// we might wrap over the periodic boundary here; that's why the condition is different from the aperiodic case
@@ -334,9 +334,9 @@
 			Bounds& vNew(v[j1]); // elt at j+1 being overwritten by the one at j and adjusted
 			vNew=v[j];
 			// inversions close the the split need special care
-			if(unlikely(j==loIdx && vi.coord<0)) { vi.period-=1; vi.coord+=v.cellDim; loIdx=v.norm(loIdx+1); }
-			else if(unlikely(j1==loIdx)) { vNew.period+=1; vNew.coord-=v.cellDim; loIdx=v.norm(loIdx-1); }
-			if(isMin && !v[j].flags.isMin && likely(doCollide && viHasBB && v[j].flags.hasBB)){
+			if(j==loIdx && vi.coord<0) { vi.period-=1; vi.coord+=v.cellDim; loIdx=v.norm(loIdx+1); }
+			else if(j1==loIdx) { vNew.period+=1; vNew.coord-=v.cellDim; loIdx=v.norm(loIdx-1); }
+			if(isMin && !v[j].flags.isMin && (doCollide && viHasBB && v[j].flags.hasBB)){
 				// see https://bugs.launchpad.net/yade/+bug/669095 and similar problem in aperiodic insertionSort
 				#if 0
 				if(vi.id==vNew.id){
@@ -344,7 +344,7 @@
 					throw runtime_error(__FILE__ ": Body's boundary metting its opposite boundary.");
 				}
 				#endif
-				if(likely(vi.id!=vNew.id)) handleBoundInversionPeri(vi.id,vNew.id,interactions,scene);
+				if((vi.id!=vNew.id)) handleBoundInversionPeri(vi.id,vNew.id,interactions,scene);
 			}
 			j=v.norm(j-1);
 		}
@@ -447,10 +447,10 @@
 				TRVAR4(pmn1,pmx1,pmn2,pmx2);
 			}
 		#endif
-		if(unlikely((pmn1!=pmx1) || (pmn2!=pmx2))){
+		if((pmn1!=pmx1) || (pmn2!=pmx2)){
 			if (allowBiggerThanPeriod) {
 				// If both bodies are bigger, we place them in the (0,0,0) period
-				if(unlikely((pmn1!=pmx1) && (pmn2!=pmx2))) {periods[axis]=0;}
+				if((pmn1!=pmx1) && (pmn2!=pmx2)) {periods[axis]=0;}
 				// else we define period with the position of the small body (we assume the big one sits in period (0,0,0), keep that in mind if velGrad(.,axis) is not a null vector)
 				else {
 					//FIXME: not sure what to do here...

=== modified file 'pkg/common/InteractionLoop.cpp'
--- pkg/common/InteractionLoop.cpp	2012-10-24 21:00:42 +0000
+++ pkg/common/InteractionLoop.cpp	2013-04-23 14:07:34 +0000
@@ -19,18 +19,8 @@
 	t=python::tuple(); // empty the args; not sure if this is OK, as there is some refcounting in raw_constructor code
 }
 
-// #define IDISP_TIMING
-
-#ifdef IDISP_TIMING
-	#define IDISP_CHECKPOINT(cpt) timingDeltas->checkpoint(cpt)
-#else
-	#define IDISP_CHECKPOINT(cpt)
-#endif
 
 void InteractionLoop::action(){
-	#ifdef IDISP_TIMING
-		timingDeltas->start();
-	#endif
 	if(eraseIntsInLoop && scene->interactions->unconditionalErasePending()>0 && !alreadyWarnedNoCollider){
 		LOG_WARN("Interactions pending erase found (erased), no collider being used?");
 		alreadyWarnedNoCollider=true;
@@ -82,7 +72,7 @@
 	#endif
 		// keep the following newline, my (edx) preprocessor outputs garbage code otherwise!
 
-		if(unlikely(removeUnseenIntrs && !I->isReal() && I->iterLastSeen<scene->iter)) {
+		if(removeUnseenIntrs && !I->isReal() && I->iterLastSeen<scene->iter) {
 			eraseAfterLoop(I->getId1(),I->getId2());
 			continue;
 		}
@@ -93,13 +83,13 @@
 		if(!b1_ || !b2_){ LOG_DEBUG("Body #"<<(b1_?I->getId2():I->getId1())<<" vanished, erasing intr #"<<I->getId1()<<"+#"<<I->getId2()<<"!"); scene->interactions->requestErase(I); continue; }
 
 		// we know there is no geometry functor already, take the short path
-		if(unlikely(!I->functorCache.geomExists)) { assert(!I->isReal()); continue; }
+		if(!I->functorCache.geomExists) { assert(!I->isReal()); continue; }
 		// no interaction geometry for either of bodies; no interaction possible
-		if(unlikely(!b1_->shape || !b2_->shape)) { assert(!I->isReal()); continue; }
+		if(!b1_->shape || !b2_->shape) { assert(!I->isReal()); continue; }
 
 		bool swap=false;
 		// IGeomDispatcher
-		if(unlikely(!I->functorCache.geom)){
+		if(!I->functorCache.geom){
 			I->functorCache.geom=geomDispatcher->getFunctor2D(b1_->shape,b2_->shape,swap);
 			// returns NULL ptr if no functor exists; remember that and shortcut
 			if(!I->functorCache.geom) {I->functorCache.geomExists=false; continue; }
@@ -108,7 +98,7 @@
 		// arguments for the geom functor are in the reverse order (dispatcher would normally call goReverse).
 		// we don't remember the fact that is reverse, so we swap bodies within the interaction
 		// and can call go in all cases
-		if(unlikely(swap)){I->swapOrder();}
+		if(swap){I->swapOrder();}
 		// body pointers must be updated, in case we swapped
 		const shared_ptr<Body>& b1=swap?b2_:b1_;
 		const shared_ptr<Body>& b2=swap?b1_:b2_;
@@ -130,25 +120,25 @@
 		}
 
 		// IPhysDispatcher
-		if(unlikely(!I->functorCache.phys)){
+		if(!I->functorCache.phys){
 			I->functorCache.phys=physDispatcher->getFunctor2D(b1->material,b2->material,swap);
 			assert(!swap); // InteractionPhysicsEngineUnits are symmetric
 		}
 		//assert(I->functorCache.phys);
-		if(unlikely(!I->functorCache.phys)){
+		if(!I->functorCache.phys){
 			throw std::runtime_error("Undefined or ambiguous IPhys dispatch for types "+b1->material->getClassName()+" and "+b2->material->getClassName()+".");
 		}
 		I->functorCache.phys->go(b1->material,b2->material,I);
 		assert(I->phys);
 
-		if(unlikely(!wasReal)) I->iterMadeReal=scene->iter; // mark the interaction as created right now
+		if(!wasReal) I->iterMadeReal=scene->iter; // mark the interaction as created right now
 
 		// LawDispatcher
 		// populating constLaw cache must be done after geom and physics dispatchers have been called, since otherwise the interaction
 		// would not have geom and phys yet.
-		if(unlikely(!I->functorCache.constLaw)){
+		if(!I->functorCache.constLaw){
 			I->functorCache.constLaw=lawDispatcher->getFunctor2D(I->geom,I->phys,swap);
-			if(unlikely(!I->functorCache.constLaw)){
+			if(!I->functorCache.constLaw){
 				LOG_FATAL("None of given Law2 functors can handle interaction #"<<I->getId1()<<"+"<<I->getId2()<<", types geom:"<<I->geom->getClassName()<<"="<<I->geom->getClassIndex()<<" and phys:"<<I->phys->getClassName()<<"="<<I->phys->getClassIndex()<<" (LawDispatcher::getFunctor2D returned empty functor)");
 				//abort();
 				exit(1);
@@ -159,7 +149,7 @@
 		I->functorCache.constLaw->go(I->geom,I->phys,I.get());
 
 		// process callbacks for this interaction
-		if(unlikely(!I->isReal())) continue; // it is possible that Law2_ functor called requestErase, hence this check
+		if(!I->isReal()) continue; // it is possible that Law2_ functor called requestErase, hence this check
 		for(size_t i=0; i<callbacksSize; i++){
 			if(callbackPtrs[i]!=NULL) (*(callbackPtrs[i]))(callbacks[i].get(),I.get());
 		}

=== modified file 'pkg/common/InteractionLoop.hpp'
--- pkg/common/InteractionLoop.hpp	2012-10-31 12:31:50 +0000
+++ pkg/common/InteractionLoop.hpp	2013-04-23 14:07:34 +0000
@@ -4,6 +4,14 @@
 #include<yade/pkg/common/Callbacks.hpp>
 #include<yade/pkg/common/Dispatching.hpp>
 
+#ifdef USE_TIMING_DELTAS
+	#define TIMING_DELTAS_CHECKPOINT(cpt) timingDeltas->checkpoint(cpt)
+	#define TIMING_DELTAS_START() timingDeltas->start()
+#else
+	#define TIMING_DELTAS_CHECKPOINT(cpt)
+	#define TIMING_DELTAS_START()
+#endif
+
 class InteractionLoop: public GlobalEngine {
 	bool alreadyWarnedNoCollider;
 	typedef std::pair<Body::id_t, Body::id_t> idPair;
@@ -26,9 +34,6 @@
 			((bool, eraseIntsInLoop, false,,"Defines if the interaction loop should erase pending interactions, else the collider takes care of that alone (depends on what collider is used)."))
 			,
 			/*ctor*/ alreadyWarnedNoCollider=false;
-				#ifdef IDISP_TIMING
-					timingDeltas=shared_ptr<TimingDeltas>(new TimingDeltas);
-				#endif
 				#ifdef YADE_OPENMP
 					eraseAfterLoopIds.resize(omp_get_max_threads());
 				#endif

=== modified file 'pkg/common/KinematicEngines.cpp'
--- pkg/common/KinematicEngines.cpp	2011-06-16 08:54:59 +0000
+++ pkg/common/KinematicEngines.cpp	2013-03-07 18:28:01 +0000
@@ -68,7 +68,9 @@
 void HarmonicMotionEngine::apply(const vector<Body::id_t>& ids){
 	if (ids.size()>0) {
 		Vector3r w = f*2.0*Mathr::PI; 										 								//Angular frequency
-		Vector3r velocity = ((((w*scene->time + fi).cwise().sin())*(-1.0)).cwise()*A).cwise()*w;	//Linear velocity at current time
+		Vector3r velocity = (((w*scene->time + fi).array().sin())*(-1.0));
+    velocity = velocity.cwiseProduct(A);
+    velocity = velocity.cwiseProduct(w);
 		FOREACH(Body::id_t id,ids){
 			assert(id<(Body::id_t)scene->bodies->size());
 			Body* b=Body::byId(id,scene).get();

=== modified file 'pkg/common/OpenGLRenderer.cpp'
--- pkg/common/OpenGLRenderer.cpp	2012-08-02 18:13:22 +0000
+++ pkg/common/OpenGLRenderer.cpp	2013-03-07 18:28:01 +0000
@@ -99,7 +99,7 @@
 		if(!(scaleDisplacements||scaleRotations||scene->isPeriodic)){ bodyDisp[id].pos=pos; bodyDisp[id].ori=ori; continue; }
 		// apply scaling
 		bodyDisp[id].pos=cellPos; // point of reference (inside the cell for periodic)
-		if(scaleDisplacements) bodyDisp[id].pos+=dispScale.cwise()*Vector3r(pos-refPos); // add scaled translation to the point of reference
+		if(scaleDisplacements) bodyDisp[id].pos+=dispScale.cwiseProduct(Vector3r(pos-refPos)); // add scaled translation to the point of reference
 		if(!scaleRotations) bodyDisp[id].ori=ori;
 		else{
 			Quaternionr relRot=refOri.conjugate()*ori;
@@ -120,7 +120,7 @@
 		if(dispScale!=Vector3r::Ones()){
 			const Matrix3r& refHSize(scene->cell->refHSize);
 			Matrix3r scaledHSize;
-			for(int i=0; i<3; i++) scaledHSize.col(i)=refHSize.col(i)+dispScale.cwise()*Vector3r(hSize.col(i)-refHSize.col(i));
+			for(int i=0; i<3; i++) scaledHSize.col(i)=refHSize.col(i)+dispScale.cwiseProduct(Vector3r(hSize.col(i)-refHSize.col(i)));
 			GLUtils::Parallelepiped(scaledHSize.col(0),scaledHSize.col(1),scaledHSize.col(2));
 		} else {
 			GLUtils::Parallelepiped(hSize.col(0),hSize.col(1),hSize.col(2));

=== modified file 'pkg/common/ParallelEngine.cpp'
--- pkg/common/ParallelEngine.cpp	2012-10-24 21:00:42 +0000
+++ pkg/common/ParallelEngine.cpp	2013-01-29 19:03:26 +0000
@@ -1,7 +1,10 @@
 #include"ParallelEngine.hpp"
 #include<boost/python.hpp>
 using namespace boost;
-//#include<omp.h> // needed for omp_get_thread_num() (debugging)
+#ifdef YADE_OPENMP
+  #include<omp.h>
+#endif
+
 YADE_PLUGIN((ParallelEngine));
 
 //! ParallelEngine's pseudo-ctor (factory), taking nested lists of slave engines (might be moved to real ctor perhaps)

=== modified file 'pkg/common/PeriodicEngines.hpp'
--- pkg/common/PeriodicEngines.hpp	2011-05-04 12:37:24 +0000
+++ pkg/common/PeriodicEngines.hpp	2013-03-26 12:03:38 +0000
@@ -14,6 +14,7 @@
 			const Real& virtNow=scene->time;
 			Real realNow=getClock();
 			const long& iterNow=scene->iter;
+			if (iterNow<iterLast) nDone=0;//handle O.resetTime(), all counters will be initialized again
 			if((nDo<0 || nDone<nDo) &&
 				((virtPeriod>0 && virtNow-virtLast>=virtPeriod) ||
 				 (realPeriod>0 && realNow-realLast>=realPeriod) ||

=== modified file 'pkg/common/ZECollider.cpp'
--- pkg/common/ZECollider.cpp	2012-01-23 14:43:54 +0000
+++ pkg/common/ZECollider.cpp	2013-03-06 17:30:45 +0000
@@ -124,9 +124,9 @@
 // 	boxesIdx.resize(scene->bodies.size());
 	boxes.clear();
 	FOREACH(shared_ptr<Body>& b, *scene->bodies){
-		if(likely(b)){
+		if(b){
 			shared_ptr<Bound>& bv=b->bound;
-			if(likely(bv)) {
+			if(bv) {
 				boxes.push_back(CGBox(CGBbox(bv->min[0],bv->min[1],bv->min[2],bv->max[0],bv->max[1],bv->max[2]),b));
 // 				boxesIdx[b->id]
 			}
@@ -145,4 +145,4 @@
 	ISC_CHECKPOINT("collide");
 }
 
-#endif
\ No newline at end of file
+#endif

=== modified file 'pkg/dem/CapillaryTriaxialTest.cpp'
--- pkg/dem/CapillaryTriaxialTest.cpp	2010-11-19 12:30:08 +0000
+++ pkg/dem/CapillaryTriaxialTest.cpp	2013-01-07 15:19:31 +0000
@@ -178,9 +178,15 @@
 			 
 	}
 	
-	
+	//convert the original sphere vector (with clump info) to a BasicSphere vector.
 	vector<BasicSphere> sphere_list;
-	if(importFilename!="") sphere_list=Shop::loadSpheresFromFile(importFilename,lowerCorner,upperCorner);
+	typedef tuple<Vector3r,Real,int> tupleVector3rRealInt;
+	if(importFilename!=""){
+		vector<tuple<Vector3r,Real,int> >sphereListClumpInfo = Shop::loadSpheresFromFile(importFilename,lowerCorner,upperCorner);
+		FOREACH(tupleVector3rRealInt t, sphereListClumpInfo){
+			sphere_list.push_back(make_pair(get<0>(t),get<1>(t)));
+		};
+	}
 	else message+=GenerateCloud_water(sphere_list, lowerCorner, upperCorner, numberOfGrains, Rdispersion, 0.75);
 	
 	vector<BasicSphere>::iterator it = sphere_list.begin();

=== modified file 'pkg/dem/CohFrictMat.hpp'
--- pkg/dem/CohFrictMat.hpp	2012-10-09 09:09:02 +0000
+++ pkg/dem/CohFrictMat.hpp	2013-03-06 20:47:43 +0000
@@ -27,10 +27,9 @@
 		((Real,normalCohesion,0,,""))
 		((Real,shearCohesion,0,,""))
 		((bool,momentRotationLaw,false,,"Use bending/twisting moment at contact. The contact will have moments only if both bodies have this flag true. See :yref:`CohFrictPhys::cohesionDisablesFriction` for details."))
-		((Real,cylCylNormalCoh,0,,"Normal cohesion between two different chained cylinders."))
-        ((Real,cylCylShearCoh,0,,"Shear cohesion between two different chained cylinders.")),
+		,
 		createIndex();
-					);
+		);
 /// Indexable
 	REGISTER_CLASS_INDEX(CohFrictMat,FrictMat);
 };

=== modified file 'pkg/dem/CohesiveFrictionalContactLaw.cpp'
--- pkg/dem/CohesiveFrictionalContactLaw.cpp	2012-09-19 16:21:56 +0000
+++ pkg/dem/CohesiveFrictionalContactLaw.cpp	2013-03-06 17:30:45 +0000
@@ -103,7 +103,7 @@
 			maxFs = maxFs / Fs;
 			Vector3r trialForce=shearForce;
 			shearForce *= maxFs;
-			if (unlikely(scene->trackEnergy)){
+			if (scene->trackEnergy){
 				Real dissip=((1/phys->ks)*(trialForce-shearForce))/*plastic disp*/ .dot(shearForce)/*active force*/;
 				if(dissip>0) scene->energy->add(dissip,"plastDissip",plastDissipIx,/*reset*/false);}
 			if (Fn<0)  phys->normalForce = Vector3r::Zero();//Vector3r::Zero()

=== modified file 'pkg/dem/CohesiveTriaxialTest.cpp'
--- pkg/dem/CohesiveTriaxialTest.cpp	2010-12-31 14:35:21 +0000
+++ pkg/dem/CohesiveTriaxialTest.cpp	2013-01-07 15:19:31 +0000
@@ -174,11 +174,18 @@
 			}
 
 	}
-
+	
+	//convert the original sphere vector (with clump info) to a BasicSphere vector.
 	vector<BasicSphere> sphere_list;
-	if(importFilename!="") sphere_list=Shop::loadSpheresFromFile(importFilename,lowerCorner,upperCorner);
+	typedef tuple<Vector3r,Real,int> tupleVector3rRealInt;
+	if(importFilename!=""){
+		vector<tuple<Vector3r,Real,int> >sphereListClumpInfo = Shop::loadSpheresFromFile(importFilename,lowerCorner,upperCorner);
+		FOREACH(tupleVector3rRealInt t, sphereListClumpInfo){
+			sphere_list.push_back(make_pair(get<0>(t),get<1>(t)));
+		};
+	}
 	else message=GenerateCloud_cohesive(sphere_list, lowerCorner, upperCorner, numberOfGrains, radiusDeviation, 0.75);
-
+	
 	vector<BasicSphere>::iterator it = sphere_list.begin();
 	vector<BasicSphere>::iterator it_end = sphere_list.end();
 

=== modified file 'pkg/dem/ConcretePM.cpp'
--- pkg/dem/ConcretePM.cpp	2012-09-01 09:11:27 +0000
+++ pkg/dem/ConcretePM.cpp	2013-05-02 12:19:32 +0000
@@ -3,8 +3,12 @@
 #include<yade/core/Scene.hpp>
 #include<yade/pkg/dem/DemXDofGeom.hpp>
 #include<yade/pkg/dem/Shop.hpp>
-
-YADE_PLUGIN((CpmState)(CpmMat)(Ip2_CpmMat_CpmMat_CpmPhys)(Ip2_FrictMat_CpmMat_FrictPhys)(CpmPhys)(Law2_SomeGeom_CpmPhys_Cpm)(Law2_Dem3DofGeom_CpmPhys_Cpm)(Law2_ScGeom_CpmPhys_Cpm)
+#include<yade/pkg/common/InteractionLoop.hpp>
+#include<yade/pkg/common/Facet.hpp>
+#include<yade/pkg/common/Wall.hpp>
+
+
+YADE_PLUGIN((CpmState)(CpmMat)(Ip2_CpmMat_CpmMat_CpmPhys)(Ip2_FrictMat_CpmMat_FrictPhys)(CpmPhys)(Law2_ScGeom_CpmPhys_Cpm)
 	#ifdef YADE_OPENGL
 		(Gl1_CpmPhys)
 	#endif	
@@ -16,9 +20,11 @@
 
 CREATE_LOGGER(Ip2_FrictMat_CpmMat_FrictPhys);
 void Ip2_FrictMat_CpmMat_FrictPhys::go(const shared_ptr<Material>& pp1, const shared_ptr<Material>& pp2, const shared_ptr<Interaction>& interaction){
+	TIMING_DELTAS_START();
 	const shared_ptr<FrictMat>& mat1 = YADE_PTR_CAST<FrictMat>(pp1);
 	const shared_ptr<CpmMat>& mat2 = YADE_PTR_CAST<CpmMat>(pp2);
 	Ip2_FrictMat_FrictMat_FrictPhys().go(mat1,mat2,interaction);
+	TIMING_DELTAS_CHECKPOINT("end of Ip2_FritPhys");
 }
 
 
@@ -28,6 +34,7 @@
 void Ip2_CpmMat_CpmMat_CpmPhys::go(const shared_ptr<Material>& pp1, const shared_ptr<Material>& pp2, const shared_ptr<Interaction>& interaction){
 	// no updates of an already existing contact necessary
 	if (interaction->phys) return;
+	TIMING_DELTAS_START();
 	shared_ptr<CpmPhys> cpmPhys(new CpmPhys());
 	interaction->phys = cpmPhys;
 	CpmMat* mat1 = YADE_CAST<CpmMat*>(pp1.get());
@@ -37,12 +44,12 @@
 	if (!mat1->neverDamage) {
 		assert(!isnan(mat1->sigmaT));
 		assert(!isnan(mat1->epsCrackOnset));
-		assert(!isnan(mat1->crackOpening) || !isnan(mat1->relDuctility));
+		assert(!isnan(mat1->relDuctility));
 	}
 	if (!mat2->neverDamage) {
 		assert(!isnan(mat2->sigmaT));
 		assert(!isnan(mat2->epsCrackOnset));
-		assert(!isnan(mat2->crackOpening) || !isnan(mat2->relDuctility));
+		assert(!isnan(mat2->relDuctility));
 	}
 
 	cpmPhys->damLaw = mat1->damLaw;
@@ -55,7 +62,6 @@
 		cpmPhys->isCohesive = (cohesiveThresholdIter < 0 || scene->iter < cohesiveThresholdIter);
 		#define _CPATTR(a) cpmPhys->a=mat1->a
 			_CPATTR(epsCrackOnset);
-			_CPATTR(crackOpening);
 			_CPATTR(relDuctility);
 			_CPATTR(neverDamage);
 			_CPATTR(dmgTau);
@@ -73,7 +79,6 @@
 			cpmPhys->undamagedCohesion = .5*(mat1->sigmaT + mat2->sigmaT);
 			cpmPhys->isCohesive = (cohesiveThresholdIter < 0 || scene->iter < cohesiveThresholdIter);
 			_AVGATTR(epsCrackOnset);
-			_AVGATTR(crackOpening);
 			_AVGATTR(relDuctility);
 			cpmPhys->neverDamage = (mat1->neverDamage || mat2->neverDamage);
 			_AVGATTR(dmgTau);
@@ -84,8 +89,9 @@
 		#undef _AVGATTR
 	}
 
-	// NOTE: some params are not assigned until in Law2_SomeGeom_CpmPhys_Cpm, since they need geometry as well; those are:
+	// NOTE: some params are not assigned until in Law2_ScGeom_CpmPhys_Cpm, since they need geometry as well; those are:
 	// 	crossSection, kn, ks, refLength
+	TIMING_DELTAS_CHECKPOINT("end of Ip2_CpmPhys");
 }
 
 
@@ -143,16 +149,94 @@
 	return 1.-exp(beta)*(1-sigmaTYield/sigmaTNorm);
 }
 
-
-
-
-
-
-
-
-
-/********************** Law2_SomeGeom_CpmPhys_Cpm ****************************/
-CREATE_LOGGER(Law2_Dem3DofGeom_CpmPhys_Cpm);
+Real CpmPhys::funcG(const Real& kappaD, const Real& epsCrackOnset, const Real& epsFracture, const bool& neverDamage, const int& damLaw) {
+	if (kappaD<epsCrackOnset || neverDamage) return 0;
+	switch (damLaw) {
+		case 0: // linear
+			return (1.-epsCrackOnset/kappaD)/(1.-epsCrackOnset/epsFracture);
+		case 1: // exponential
+			return 1.-(epsCrackOnset/kappaD)*exp(-(kappaD-epsCrackOnset)/epsFracture);
+	}
+	throw runtime_error("CpmPhys::funcG: wrong damLaw\n");
+}
+
+Real CpmPhys::funcGDKappa(const Real& kappaD, const Real& epsCrackOnset, const Real& epsFracture, const bool& neverDamage, const int& damLaw) {
+	switch (damLaw) {
+		case 0: // linear
+			return epsCrackOnset / ((1.-epsCrackOnset/epsFracture)*kappaD*kappaD);
+		case 1: // exponential
+			return epsCrackOnset/kappaD * (1./kappaD + 1./epsFracture) * exp(-(kappaD-epsCrackOnset)/epsFracture);
+	}
+	throw runtime_error("CpmPhys::funcGDKappa: wrong damLaw\n");
+}
+
+Real CpmPhys::funcGInv(const Real& omega, const Real& epsCrackOnset, const Real& epsFracture, const bool& neverDamage, const int& damLaw) {
+	if (omega==0. || neverDamage) return 0;
+	switch (damLaw) {
+		case 0: // linear
+			return epsCrackOnset / (1. - omega*(1. - epsCrackOnset/epsFracture));
+		case 1: // exponential
+			// Newton's iterations
+			Real fg,dfg,decr,ret=epsCrackOnset,tol=1e-3;
+			int maxIter = 100;
+			for (int i=0; i<maxIter; i++) {
+				fg = - omega + 1. - epsCrackOnset/ret * exp(-(ret-epsCrackOnset)/epsFracture);
+				//dfg = (epsCrackOnset/ret/ret - epsCrackOnset*(ret-epsCrackOnset)/ret/epsFracture/epsFracture) * exp(-(ret-epsCrackOnset)/epsFracture);
+				dfg = CpmPhys::funcGDKappa(ret,epsCrackOnset,epsFracture,neverDamage,damLaw);
+				decr = fg/dfg;
+				ret -= decr;
+				if (fabs(decr/epsCrackOnset) < tol) {
+					return ret;
+				}
+			}
+			throw runtime_error("CpmPhys::funcGInv: no convergence\n");
+	}
+	throw runtime_error("CpmPhys::funcGInv: wrong damLaw\n");
+}
+
+void CpmPhys::setDamage(Real dmg) {
+	if (neverDamage) { return; }
+	omega = dmg;
+	kappaD = CpmPhys::funcGInv(dmg,epsCrackOnset,epsFracture,neverDamage,damLaw);
+}
+
+void CpmPhys::setRelResidualStrength(Real r) {
+	if (neverDamage) { return; }
+	if (r == 1.) {
+		relResidualStrength = r;
+		kappaD = omega = 0.;
+		return;
+	}
+	Real k = epsFracture;
+	Real g,dg,f,df,tol=1e-3,e0i=1./epsCrackOnset,decr;
+	int maxIter = 100;
+	int i;
+	for (i=0; i<maxIter; i++) {
+		g = CpmPhys::funcG(k,epsCrackOnset,epsFracture,neverDamage,damLaw);
+		dg = CpmPhys::funcGDKappa(k,epsCrackOnset,epsFracture,neverDamage,damLaw);
+		f = -r + (1-g)*k*e0i;
+		df = e0i*(1-g-k*dg);
+		decr = f/df;
+		k -= decr;
+		if (fabs(decr) < tol) {
+			kappaD = k;
+			omega = CpmPhys::funcG(k,epsCrackOnset,epsFracture,neverDamage,damLaw);
+			relResidualStrength = r;
+			return;
+		}
+	}
+	throw runtime_error("CpmPhys::setRelResidualStrength: no convergence\n");
+}
+
+
+
+
+
+
+
+
+/********************** Law2_ScGeom_CpmPhys_Cpm ****************************/
+CREATE_LOGGER(Law2_ScGeom_CpmPhys_Cpm);
 
 #ifdef YADE_CPM_FULL_MODEL_AVAILABLE
 	#include"../../../brefcom-mm.hh"
@@ -161,59 +245,16 @@
 // #undef CPM_MATERIAL_MODEL (force trunk version of the model)
 
 
-#ifdef CPM_MATERIAL_MODEL
-	#define CPM_MATERIAL_MODEL_A \
-		Real& epsNPl(BC->epsNPl);\
-		const Real& dt = scene->dt;\
-		const Real& dmgTau(BC->dmgTau);\
-		const Real& plTau(BC->plTau);\
-		const Real& yieldLogSpeed(this->yieldLogSpeed);\
-		const int& yieldSurfType(this->yieldSurfType);\
-		const Real& yieldEllipseShift(this->yieldEllipseShift);\
-		const Real& epsSoft(this->epsSoft);\
-		const Real& relKnSoft(this->relKnSoft);
-#else
-	#define CPM_MATERIAL_MODEL_A
-#endif
-
-
-// constitutive law 
-#ifdef CPM_MATERIAL_MODEL
-	#define CPM_MATERIAL_MODEL_B \
-		/* complicated version */ \
-		if (epsSoft >= 0) epsN += BC->isoPrestress/E; \
-		else { /* take softening into account for the prestress */ \
-			Real sigmaSoft=E*epsSoft;\
-			if (BC->isoPrestress >= sigmaSoft) epsN += BC -> isoPrestress/E; /* on the non-softened branch yet */ \
-			/* otherwise take the regular and softened branches separately (different moduli) */ \
-			else epsN += sigmaSoft/E+(BC->isoPrestress-sigmaSoft)/(E*relKnSoft);\
-		} \
-		CPM_MATERIAL_MODEL
-#else
-	#define CPM_MATERIAL_MODEL_B \
-		/* simplified public model */ \
-		epsN += BC->isoPrestress/E; \
-		/* very simplified version of the constitutive law */ \
-		kappaD = max(max(0.,epsN),kappaD); /* internal variable, max positive strain (non-decreasing) */ \
-		/* Real epsFracture = crackOpening/contGeom->refLength; */ \
-		omega = isCohesive? funcG(kappaD,epsCrackOnset,epsFracture,neverDamage,damLaw) : 1.; /* damage variable (non-decreasing, as funcG is also non-decreasing) */ \
-		sigmaN = (1-(epsN>0?omega:0))*E*epsN; /* damage taken in account in tension only */ \
-		sigmaT = G*epsT; /* trial stress */ \
-		Real yieldSigmaT = max((Real)0.,undamagedCohesion*(1-omega)-sigmaN*tanFrictionAngle); /* Mohr-Coulomb law with damage */ \
-		if (sigmaT.squaredNorm() > yieldSigmaT*yieldSigmaT) { \
-			Real scale = yieldSigmaT/sigmaT.norm(); \
-			sigmaT *= scale; /* stress return */ \
-			epsT *= scale; \
-			/* epsPlSum += yieldSigmaT*contGeom->slipToStrainTMax(yieldSigmaT/G);*/ /* adjust strain */ \
-		} \
-		relResidualStrength = isCohesive? (kappaD<epsCrackOnset? 1. : (1-omega)*(kappaD)/epsCrackOnset) : 0;
-#endif
+
+
+
+
 
 
 #ifdef YADE_DEBUG
 	#define CPM_YADE_DEBUG_A \
 		if(isnan(epsN)){\
-			/*LOG_FATAL("refLength="<<contGeom->refLength<<"; pos1="<<contGeom->se31.position<<"; pos2="<<contGeom->se32.position<<"; displacementN="<<contGeom->displacementN());*/ \
+			/*LOG_FATAL("refLength="<<geom->refLength<<"; pos1="<<geom->se31.position<<"; pos2="<<geom->se32.position<<"; displacementN="<<geom->displacementN());*/ \
 			throw runtime_error("!! epsN==NaN !!");\
 		}
 #else
@@ -225,135 +266,149 @@
 #define NNAN(a) YADE_VERIFY(!isnan(a));
 #define NNANV(v) YADE_VERIFY(!isnan(v[0])); assert(!isnan(v[1])); assert(!isnan(v[2]));
 
-
-
-#define CPM_GO_A \
-	/* just the first time */ \
-	if (I->isFresh(scene)) { \
-		Vector3r pos1 = scene->bodies->operator[](I->id1)->state->pos; \
-		Vector3r pos2 = scene->bodies->operator[](I->id2)->state->pos; \
-		if (scene->isPeriodic) { \
-			Vector3r temp = pos2 - pos1; \
-			pos1 = scene->cell->wrapShearedPt(pos1); \
-			pos2 = pos1 + temp; \
-		} \
-		Real minRad = (contGeom->refR1 <= 0? contGeom->refR2 : (contGeom->refR2 <=0? contGeom->refR1 : min(contGeom->refR1,contGeom->refR2))); \
-		BC->refLength = (pos2 - pos1).norm(); \
-		BC->crossSection = Mathr::PI*pow(minRad,2); \
-		BC->refPD = contGeom->refR1 + contGeom->refR2 - BC->refLength; \
-		BC->kn = BC->crossSection*BC->E/BC->refLength; \
-		BC->ks = BC->crossSection*BC->G/BC->refLength; \
-		BC->epsFracture = isnan(BC->crackOpening)? BC->epsCrackOnset*BC->relDuctility : BC->crackOpening/(2*minRad); /* *contGeom->refLength */; \
-	} \
-	\
-	/* shorthands */ \
-	Real& epsN(BC->epsN); \
-	Vector3r& epsT(BC->epsT); \
-	Real& kappaD(BC->kappaD); \
-	/* Real& epsPlSum(BC->epsPlSum); */ \
-	const Real& E(BC->E); \
-	const Real& undamagedCohesion(BC->undamagedCohesion); \
-	const Real& tanFrictionAngle(BC->tanFrictionAngle); \
-	const Real& G(BC->G); \
-	const Real& crossSection(BC->crossSection); \
-	const Real& omegaThreshold(this->omegaThreshold); \
-	const Real& epsCrackOnset(BC->epsCrackOnset); \
-	Real& relResidualStrength(BC->relResidualStrength); \
-	/*const Real& crackOpening(BC->crackOpening); */ \
-	/*const Real& relDuctility(BC->relDuctility); */ \
-	const Real& epsFracture(BC->epsFracture); \
-	const int& damLaw(BC->damLaw); \
-	const bool& neverDamage(BC->neverDamage); \
-	Real& omega(BC->omega); \
-	Real& sigmaN(BC->sigmaN); \
-	Vector3r& sigmaT(BC->sigmaT); \
-	Real& Fn(BC->Fn); \
-	Vector3r& Fs(BC->Fs); /* for python access */ \
-	const bool& isCohesive(BC->isCohesive); \
-	\
-	CPM_MATERIAL_MODEL_A
-
-#define CPM_GO_B \
-	/* debugging */ \
-	CPM_YADE_DEBUG_A \
-	\
-	NNAN(epsN); NNANV(epsT); \
-	\
-	/* constitutive law */ \
-	CPM_MATERIAL_MODEL_B \
-	\
-	sigmaN -= BC->isoPrestress; \
-	\
-	NNAN(kappaD); NNAN(epsFracture); NNAN(omega); \
-	NNAN(sigmaN); NNANV(sigmaT); NNAN(crossSection); \
-	\
-	/* handle broken contacts */ \
-	if (epsN>0. && ((isCohesive && omega>omegaThreshold) || !isCohesive)) { \
-		/* if (isCohesive) { */ \
-			 const shared_ptr<Body>& body1 = Body::byId(I->getId1(),scene), body2 = Body::byId(I->getId2(),scene); assert(body1); assert(body2); \
-			 const shared_ptr<CpmState>& st1 = YADE_PTR_CAST<CpmState>(body1->state), st2 = YADE_PTR_CAST<CpmState>(body2->state); \
-			/* nice article about openMP::critical vs. scoped locks: http://www.thinkingparallel.com/2006/08/21/scoped-locking-vs-critical-in-openmp-a-personal-shootout/ */ \
-			{ boost::mutex::scoped_lock lock(st1->updateMutex); st1->numBrokenCohesive += 1; /* st1->epsPlBroken += epsPlSum; */ } \
-			{ boost::mutex::scoped_lock lock(st2->updateMutex); st2->numBrokenCohesive += 1; /* st2->epsPlBroken += epsPlSum; */ } \
-		/* } */ \
-		scene->interactions->requestErase(I); \
-		return; \
-	} \
-	\
-	Fn = sigmaN*crossSection; BC->normalForce = Fn*contGeom->normal; \
-	Fs = sigmaT*crossSection; BC->shearForce = Fs;
-
-
-
-
-
-
-void Law2_Dem3DofGeom_CpmPhys_Cpm::go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I){
-	Dem3DofGeom* contGeom = static_cast<Dem3DofGeom*>(_geom.get());
-	CpmPhys* BC = static_cast<CpmPhys*>(_phys.get());
-	
-	//#define CPM_LAW2 Law2_Dem3DofGeom_CpmPhys_Cpm
-	CPM_GO_A
-
-	epsN = contGeom->strainN();
-	epsT = contGeom->strainT();
-
-	CPM_GO_B
-
-	applyForceAtContactPoint(BC->normalForce + BC->shearForce, contGeom->contactPoint, I->getId1(), contGeom->se31.position, I->getId2(), contGeom->se32.position);
-}
-
-
-
-
-
-CREATE_LOGGER(Law2_ScGeom_CpmPhys_Cpm);
 void Law2_ScGeom_CpmPhys_Cpm::go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I){
-	ScGeom* contGeom=static_cast<ScGeom*>(_geom.get());
-	CpmPhys* BC=static_cast<CpmPhys*>(_phys.get());
-
-	//#define CPM_LAW2 Law2_ScGeom_CpmPhys_Cpm
-	CPM_GO_A
-	
-	epsN = - (-BC->refPD + contGeom->penetrationDepth) / BC->refLength;
-	epsT = contGeom->rotate(epsT);
-	epsT += contGeom->shearIncrement() / (BC->refLength + BC->refPD) ; 
-
-	CPM_GO_B
-
-	Vector3r pos1,pos2;
-	if (scene->isPeriodic) {
-		pos1 = scene->bodies->operator[](I->id1)->state->pos;
-		pos2 = scene->bodies->operator[](I->id2)->state->pos;
-		Vector3r temp = pos2 - pos1;
-		pos1 = scene->cell->wrapShearedPt(pos1);
-		pos2 = pos1 + temp;
+	TIMING_DELTAS_START();
+	ScGeom* geom=static_cast<ScGeom*>(_geom.get());
+	CpmPhys* phys=static_cast<CpmPhys*>(_phys.get());
+
+	/* just the first time */
+	if (I->isFresh(scene)) {
+		const shared_ptr<Body> b1 = Body::byId(I->id1,scene);
+		const shared_ptr<Body> b2 = Body::byId(I->id2,scene);
+		const int sphereIndex = Sphere::getClassIndexStatic();
+		const int facetIndex = Facet::getClassIndexStatic();
+		const int wallIndex = Wall::getClassIndexStatic();
+		const int b1index = b1->shape->getClassIndex();
+		const int b2index = b2->shape->getClassIndex();
+		if (b1index == sphereIndex && b2index == sphereIndex) { // both bodies are spheres
+			const Vector3r& pos1 = Body::byId(I->id1,scene)->state->pos;
+			const Vector3r& pos2 = Body::byId(I->id2,scene)->state->pos;
+			Real minRad = (geom->refR1 <= 0? geom->refR2 : (geom->refR2 <=0? geom->refR1 : min(geom->refR1,geom->refR2)));
+			Vector3r shift2 = scene->isPeriodic? Vector3r(scene->cell->hSize*I->cellDist.cast<Real>()) : Vector3r::Zero();
+			phys->refLength = (pos2 - pos1 + shift2).norm();
+			phys->crossSection = Mathr::PI*pow(minRad,2);
+			phys->refPD = geom->refR1 + geom->refR2 - phys->refLength;
+		} else if (b1index == facetIndex || b2index == facetIndex || b1index == wallIndex || b2index == wallIndex) { // one body is facet or wall
+			shared_ptr<Body> sphere, plane;
+			if (b1index == facetIndex || b1index == wallIndex) { plane = b1; sphere = b2; }
+			else { plane = b2; sphere = b1; }
+			Real rad = ( (Sphere*) sphere->shape.get() )->radius;
+			phys->refLength = rad;
+			phys->crossSection = Mathr::PI*pow(rad,2);
+			phys->refPD = 0.;
+		}
+		phys->kn = phys->crossSection*phys->E/phys->refLength;
+		phys->ks = phys->crossSection*phys->G/phys->refLength;
+		phys->epsFracture = phys->epsCrackOnset*phys->relDuctility;
+	}
+	
+	/* shorthands */
+	Real& epsN(phys->epsN);
+	Vector3r& epsT(phys->epsT);
+	Real& kappaD(phys->kappaD);
+	/* Real& epsPlSum(phys->epsPlSum); */
+	const Real& E(phys->E); \
+	const Real& undamagedCohesion(phys->undamagedCohesion);
+	const Real& tanFrictionAngle(phys->tanFrictionAngle);
+	const Real& G(phys->G);
+	const Real& crossSection(phys->crossSection);
+	const Real& omegaThreshold(this->omegaThreshold);
+	const Real& epsCrackOnset(phys->epsCrackOnset);
+	Real& relResidualStrength(phys->relResidualStrength);
+	/*const Real& relDuctility(phys->relDuctility); */
+	const Real& epsFracture(phys->epsFracture);
+	const int& damLaw(phys->damLaw);
+	const bool& neverDamage(phys->neverDamage);
+	Real& omega(phys->omega);
+	Real& sigmaN(phys->sigmaN);
+	Vector3r& sigmaT(phys->sigmaT);
+	Real& Fn(phys->Fn);
+	Vector3r& Fs(phys->Fs); /* for python access */
+	const bool& isCohesive(phys->isCohesive);
+
+	#ifdef CPM_MATERIAL_MODEL
+		Real& epsNPl(phys->epsNPl);
+		const Real& dt = scene->dt;
+		const Real& dmgTau(phys->dmgTau);
+		const Real& plTau(phys->plTau);
+		const Real& yieldLogSpeed(this->yieldLogSpeed);
+		const int& yieldSurfType(this->yieldSurfType);
+		const Real& yieldEllipseShift(this->yieldEllipseShift);
+		const Real& epsSoft(this->epsSoft);
+		const Real& relKnSoft(this->relKnSoft);
+	#endif
+
+	TIMING_DELTAS_CHECKPOINT("GO A");
+	
+	epsN = - (-phys->refPD + geom->penetrationDepth) / phys->refLength;
+	epsT = geom->rotate(epsT);
+	epsT += geom->shearIncrement() / (phys->refLength + phys->refPD) ; 
+
+	/* debugging */
+	CPM_YADE_DEBUG_A
+
+	NNAN(epsN); NNANV(epsT);
+
+	/* constitutive law */
+	#ifdef CPM_MATERIAL_MODEL
+		CPM_MATERIAL_MODEL
+	#else
+		/* simplified public model */
+		epsN += phys->isoPrestress/E;
+		/* very simplified version of the constitutive law */
+		kappaD = max(max(0.,epsN),kappaD); /* internal variable, max positive strain (non-decreasing) */
+		omega = isCohesive? phys->funcG(kappaD,epsCrackOnset,epsFracture,neverDamage,damLaw) : 1.; /* damage variable (non-decreasing, as funcG is also non-decreasing) */
+		sigmaN = (1-(epsN>0?omega:0))*E*epsN; /* damage taken in account in tension only */
+		sigmaT = G*epsT; /* trial stress */
+		Real yieldSigmaT = max((Real)0.,undamagedCohesion*(1-omega)-sigmaN*tanFrictionAngle); /* Mohr-Coulomb law with damage */
+		if (sigmaT.squaredNorm() > yieldSigmaT*yieldSigmaT) {
+			Real scale = yieldSigmaT/sigmaT.norm();
+			sigmaT *= scale; /* stress return */
+			epsT *= scale;
+			/* epsPlSum += yieldSigmaT*geom->slipToStrainTMax(yieldSigmaT/G);*/ /* adjust strain */
+		}
+		relResidualStrength = isCohesive? (kappaD<epsCrackOnset? 1. : (1-omega)*(kappaD)/epsCrackOnset) : 0;
+	#endif
+
+	sigmaN -= phys->isoPrestress;
+
+	NNAN(kappaD); NNAN(epsFracture); NNAN(omega);
+	NNAN(sigmaN); NNANV(sigmaT); NNAN(crossSection);
+
+	/* handle broken contacts */
+	if (epsN>0. && ((isCohesive && omega>omegaThreshold) || !isCohesive)) {
+		/* if (isCohesive) { */
+			 const shared_ptr<Body>& body1 = Body::byId(I->getId1(),scene), body2 = Body::byId(I->getId2(),scene); assert(body1); assert(body2);
+			 const shared_ptr<CpmState>& st1 = YADE_PTR_CAST<CpmState>(body1->state), st2 = YADE_PTR_CAST<CpmState>(body2->state);
+			/* nice article about openMP::critical vs. scoped locks: http://www.thinkingparallel.com/2006/08/21/scoped-locking-vs-critical-in-openmp-a-personal-shootout/ */
+			{ boost::mutex::scoped_lock lock(st1->updateMutex); st1->numBrokenCohesive += 1; /* st1->epsPlBroken += epsPlSum; */ }
+			{ boost::mutex::scoped_lock lock(st2->updateMutex); st2->numBrokenCohesive += 1; /* st2->epsPlBroken += epsPlSum; */ }
+		/* } */
+		scene->interactions->requestErase(I);
+		return;
+	}
+
+	Fn = sigmaN*crossSection; phys->normalForce = -Fn*geom->normal;
+	Fs = sigmaT*crossSection; phys->shearForce = -Fs;
+
+	TIMING_DELTAS_CHECKPOINT("GO B");
+
+	Body::id_t id1 = I->getId1();
+ 	Body::id_t id2 = I->getId2();
+
+	State* b1 = Body::byId(id1,scene)->state.get();
+	State* b2 = Body::byId(id2,scene)->state.get();	
+
+	Vector3r f = -phys->normalForce - phys->shearForce;
+	if (!scene->isPeriodic) {
+		applyForceAtContactPoint(f, geom->contactPoint , id1, b1->se3.position, id2, b2->se3.position);
 	} else {
-		pos1 = scene->bodies->operator[](I->id1)->state->pos;
-		pos2 = scene->bodies->operator[](I->id2)->state->pos;
+		scene->forces.addForce(id1,f);
+		scene->forces.addForce(id2,-f);
+		scene->forces.addTorque(id1,(geom->radius1+.5*(phys->refPD-geom->penetrationDepth))*geom->normal.cross(f));
+		scene->forces.addTorque(id2,(geom->radius2+.5*(phys->refPD-geom->penetrationDepth))*geom->normal.cross(f));
 	}
-
-	applyForceAtContactPoint(BC->normalForce + BC->shearForce, contGeom->contactPoint, I->getId1(), pos1, I->getId2(), pos2);
+	TIMING_DELTAS_CHECKPOINT("rest");
 }
 
 
@@ -381,36 +436,40 @@
 
 
 	void Gl1_CpmPhys::go(const shared_ptr<IPhys>& ip, const shared_ptr<Interaction>& i, const shared_ptr<Body>& b1, const shared_ptr<Body>& b2, bool wireFrame){
-		const shared_ptr<CpmPhys>& BC = static_pointer_cast<CpmPhys>(ip);
+		const shared_ptr<CpmPhys>& phys = static_pointer_cast<CpmPhys>(ip);
 		const shared_ptr<GenericSpheresContact>& geom = YADE_PTR_CAST<GenericSpheresContact>(i->geom);
 		// FIXME: get the scene for periodicity; ugly!
 		Scene* scene=Omega::instance().getScene().get();
 
-		//Vector3r lineColor(BC->omega,1-BC->omega,0.0); /* damaged links red, undamaged green */
-		Vector3r lineColor = Shop::scalarOnColorScale(1.-BC->relResidualStrength);
+		//Vector3r lineColor(phys->omega,1-phys->omega,0.0); /* damaged links red, undamaged green */
+		Vector3r lineColor = Shop::scalarOnColorScale(1.-phys->relResidualStrength);
 
-		if(colorStrainRatio>0) lineColor = Shop::scalarOnColorScale(BC->epsN/(BC->epsCrackOnset*colorStrainRatio));
+		if(colorStrainRatio>0) lineColor = Shop::scalarOnColorScale(phys->epsN/(phys->epsCrackOnset*colorStrainRatio));
 
 		// FIXME: should be computed by the renderer; for now, use the real values
 		//Vector3r pos1=geom->se31.position, pos2=geom->se32.position;
 		Vector3r pos1 = scene->bodies->operator[](i->id1)->state->pos, pos2 = scene->bodies->operator[](i->id2)->state->pos;
+		if (scene->isPeriodic) {
+			Vector3r dPos = pos2 - pos1;
+			pos1=scene->cell->wrapShearedPt(pos1);
+			Vector3r shift2 = scene->isPeriodic? Vector3r(scene->cell->hSize*i->cellDist.cast<Real>()) : Vector3r::Zero();\
+			pos2 = pos1 + dPos + shift2;
+			//phys->refLength = (pos2 - pos1 + shift2).norm();
+			//pos2=pos1+(geom->se32.position-geom->se31.position);
+		}
 		/*
-		if(scene->isPeriodic){
-			pos1=scene->cell->wrapShearedPt(pos1);
-			pos2=pos1+(geom->se32.position-geom->se31.position);
-		}
-		*/
 		if (scene->isPeriodic) {
 			Vector3r temp = pos2 - pos1;
 			pos1 = scene->cell->wrapShearedPt(pos1);
 			pos2 = pos1 + temp;
 		}
+		*/
 
 		if (contactLine) GLUtils::GLDrawLine(pos1,pos2,lineColor);
-		if (dmgLabel) { GLUtils::GLDrawNum(BC->omega,0.5*(pos1+pos2),lineColor); }
-		else if (epsNLabel) { GLUtils::GLDrawNum(BC->epsN,0.5*(pos1+pos2),lineColor); }
-		if (BC->omega>0 && dmgPlane) {
-			Real halfSize = sqrt(1-BC->relResidualStrength)*.5*.705*sqrt(BC->crossSection);
+		if (dmgLabel) { GLUtils::GLDrawNum(phys->omega,0.5*(pos1+pos2),lineColor); }
+		else if (epsNLabel) { GLUtils::GLDrawNum(phys->epsN,0.5*(pos1+pos2),lineColor); }
+		if (phys->omega>0 && dmgPlane) {
+			Real halfSize = sqrt(1-phys->relResidualStrength)*.5*.705*sqrt(phys->crossSection);
 			Vector3r midPt = .5*Vector3r(pos1+pos2);
 			glDisable(GL_CULL_FACE);
 			glPushMatrix();
@@ -433,10 +492,10 @@
 		Vector3r cp = static_pointer_cast<GenericSpheresContact>(i->geom)->contactPoint;
 		if (scene->isPeriodic) {cp = scene->cell->wrapShearedPt(cp);}
 		if (epsT) {
-			Real maxShear = (BC->undamagedCohesion-BC->sigmaN*BC->tanFrictionAngle)/BC->G;
-			Real relShear = BC->epsT.norm()/maxShear;
-			Real scale = BC->refLength;
-			Vector3r dirShear = BC->epsT; dirShear.normalize();
+			Real maxShear = (phys->undamagedCohesion-phys->sigmaN*phys->tanFrictionAngle)/phys->G;
+			Real relShear = phys->epsT.norm()/maxShear;
+			Real scale = phys->refLength;
+			Vector3r dirShear = phys->epsT; dirShear.normalize();
 			if(epsTAxes){
 				GLUtils::GLDrawLine(cp-Vector3r(scale,0,0),cp+Vector3r(scale,0,0));
 				GLUtils::GLDrawLine(cp-Vector3r(0,scale,0),cp+Vector3r(0,scale,0));
@@ -445,9 +504,9 @@
 			GLUtils::GLDrawArrow(cp,cp+dirShear*relShear*scale,Vector3r(1.,0.,0.));
 			GLUtils::GLDrawLine(cp+dirShear*relShear*scale,cp+dirShear*scale,Vector3r(.3,.3,.3));
 
-			/* normal strain */ GLUtils::GLDrawArrow(cp,cp+geom->normal*(BC->epsN/maxShear),Vector3r(0.,1.,0.));
+			/* normal strain */ GLUtils::GLDrawArrow(cp,cp+geom->normal*(phys->epsN/maxShear),Vector3r(0.,1.,0.));
 		}
-		//if(normal) GLUtils::GLDrawArrow(cp,cp+geom->normal*.5*BC->equilibriumDist,Vector3r(0.,1.,0.));
+		//if(normal) GLUtils::GLDrawArrow(cp,cp+geom->normal*.5*phys->equilibriumDist,Vector3r(0.,1.,0.));
 	}
 #endif
 
@@ -502,8 +561,8 @@
 			}
 		}
 	}
-	Matrix3r m3i; m3i<<0.4,-0.1,-0.1, -0.1,0.4,-0.1, -0.1,-0.1,0.4; // inversion of Matrix3r(3,1,1, 1,3,1, 1,1,3)
-	Vector3r temp;
+	Matrix3r identity = Matrix3r::Identity();
+	Real tr;
 	FOREACH(shared_ptr<Body> B, *scene->bodies){
 		if (!B) continue;
 		const Body::id_t& id = B->getId();
@@ -520,12 +579,8 @@
 			}
 			Matrix3r& dmgRhs = bodyStats[id].dmgRhs;
 			dmgRhs *= 15./cohLinksWhenever;
-			temp = m3i*dmgRhs.diagonal();
-			Matrix3r& damageTensor = state->damageTensor;
-			for (int i=0; i<3; i++) { damageTensor(i,i) = temp(i); }
-			damageTensor(0,1) = damageTensor(1,0) = dmgRhs(0,1);
-			damageTensor(1,2) = damageTensor(2,1) = dmgRhs(1,2);
-			damageTensor(2,0) = damageTensor(0,2) = dmgRhs(2,0);
+			tr = 3*state->normDmg;
+			state->damageTensor = .5 * (dmgRhs - tr*identity);
 		}
 		else { state->normDmg = 0; /*state->normEpsPl=0;*/ state->damageTensor = Matrix3r::Zero(); }
 		B->shape->color = Vector3r(state->normDmg,1-state->normDmg,B->state->blockedDOFs==State::DOF_ALL?0:1);

=== modified file 'pkg/dem/ConcretePM.hpp'
--- pkg/dem/ConcretePM.hpp	2012-11-22 14:32:53 +0000
+++ pkg/dem/ConcretePM.hpp	2013-04-24 19:49:00 +0000
@@ -17,8 +17,8 @@
 3. CpmPhys (Cpm (interaction)Physics) holds various parameters as well as internal
    variables of the contact that can change as result of plasticity, damage, viscosity.
 
-4. Law2_Dem3DofGeom_CpmPhys_Cpm is constitutive law that takes geometry of the interaction
-	(Dem3Dof, which can be either Dem3Dof_SphereSphere or Dem3Dof_FacetSphere) and
+4. Law2_ScGeom_CpmPhys_Cpm is constitutive law that takes geometry of the interaction
+	(ScGeom) and
 	CpmPhys, computing forces on both bodies and updating contact variables.
 
 	The model itself is defined in the macro CPM_MATERIAL_MODEL, but due to 
@@ -99,13 +99,12 @@
 		virtual shared_ptr<State> newAssocState() const { return shared_ptr<State>(new CpmState); }
 		virtual bool stateTypeOk(State* s) const { return (bool)dynamic_cast<CpmState*>(s); }
 
-	YADE_CLASS_BASE_DOC_ATTRS_CTOR(CpmMat,FrictMat,"Concrete material, for use with other Cpm classes. \n\n.. note::\n\n\t:yref:`Density<Material::density>` is initialized to 4800 kgm⁻³automatically, which gives approximate 2800 kgm⁻³ on 0.5 density packing.\n\nConcrete Particle Model (CPM)\n\n\n:yref:`CpmMat` is particle material, :yref:`Ip2_CpmMat_CpmMat_CpmPhys` averages two particles' materials, creating :yref:`CpmPhys`, which is then used in interaction resultion by :yref:`Law2_Dem3DofGeom_CpmPhys_Cpm` or :yref:`Law2_ScGeom_CpmPhys_Cpm`. :yref:`CpmState` is associated to :yref:`CpmMat` and keeps state defined on particles rather than interactions (such as number of completely damaged interactions).\n\nThe model is contained in externally defined macro CPM_MATERIAL_MODEL, which features damage in tension, plasticity in shear and compression and rate-dependence. For commercial reasons, rate-dependence and compression-plasticity is not present in reduced version of the model, used when CPM_MATERIAL_MODEL is not defined. The full model will be described in detail in my (Václav Šmilauer) thesis along with calibration procedures (rigidity, poisson's ratio, compressive/tensile strength ratio, fracture energy, behavior under confinement, rate-dependent behavior).\n\nEven the public model is useful enough to run simulation on concrete samples, such as :ysrc:`uniaxial tension-compression test<examples/concrete/uniax.py>`.",
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR(CpmMat,FrictMat,"Concrete material, for use with other Cpm classes. \n\n.. note::\n\n\t:yref:`Density<Material::density>` is initialized to 4800 kgm⁻³automatically, which gives approximate 2800 kgm⁻³ on 0.5 density packing.\n\nConcrete Particle Model (CPM)\n\n\n:yref:`CpmMat` is particle material, :yref:`Ip2_CpmMat_CpmMat_CpmPhys` averages two particles' materials, creating :yref:`CpmPhys`, which is then used in interaction resultion by :yref:`Law2_ScGeom_CpmPhys_Cpm`. :yref:`CpmState` is associated to :yref:`CpmMat` and keeps state defined on particles rather than interactions (such as number of completely damaged interactions).\n\nThe model is contained in externally defined macro CPM_MATERIAL_MODEL, which features damage in tension, plasticity in shear and compression and rate-dependence. For commercial reasons, rate-dependence and compression-plasticity is not present in reduced version of the model, used when CPM_MATERIAL_MODEL is not defined. The full model will be described in detail in my (Václav Šmilauer) thesis along with calibration procedures (rigidity, poisson's ratio, compressive/tensile strength ratio, fracture energy, behavior under confinement, rate-dependent behavior).\n\nEven the public model is useful enough to run simulation on concrete samples, such as :ysrc:`uniaxial tension-compression test<examples/concrete/uniax.py>`.",
 		((Real,sigmaT,NaN,,"Initial cohesion [Pa]"))
 		((bool,neverDamage,false,,"If true, no damage will occur (for testing only)."))
 		((Real,epsCrackOnset,NaN,,"Limit elastic strain [-]"))
-		((Real,crackOpening,NaN,,"Crack opening when the crack is fully broken in tension. [m]"))
 		((Real,relDuctility,NaN,,"relative ductility of bonds in normal direction"))
-		((int,damLaw,1,,"Law for gamage evolution in uniaxial tension. 0 for linear stress-strain softening branch, 1 for exponential damage evolution law"))
+		((int,damLaw,1,,"Law for damage evolution in uniaxial tension. 0 for linear stress-strain softening branch, 1 (default) for exponential damage evolution law"))
 		((Real,dmgTau,((void)"deactivated if negative",-1),,"Characteristic time for normal viscosity. [s]"))
 		((Real,dmgRateExp,0,,"Exponent for normal viscosity function. [-]"))
 		((Real,plTau,((void)"deactivated if negative",-1),,"Characteristic time for visco-plasticity. [s]"))
@@ -132,14 +131,14 @@
 
 /*! @brief representation of a single interaction of the CPM type: storage for relevant parameters.
  *
- * Evolution of the contact is governed by Law2_Dem3DofGeom_CpmPhys_Cpm:
+ * Evolution of the contact is governed by Law2_ScGeom_CpmPhys_Cpm:
  * that includes damage effects and chages of parameters inside CpmPhys.
  *
  */
 class CpmPhys: public NormShearPhys {
 	public:
 		static long cummBetaIter, cummBetaCount;
-		/*! auxiliary variable for visualization, recalculated in Law2_Dem3DofGeom_CpmPhys_Cpm at every iteration */
+		/*! auxiliary variable for visualization, recalculated in Law2_ScGeom_CpmPhys_Cpm at every iteration */
 		// Fn and Fs are also stored as Vector3r normalForce, shearForce in NormShearPhys 
 		Real omega, Fn, sigmaN, epsN, relResidualStrength; Vector3r sigmaT, Fs;
 
@@ -147,8 +146,16 @@
 		Real computeDmgOverstress(Real dt);
 		Real computeViscoplScalingFactor(Real sigmaTNorm, Real sigmaTYield,Real dt);
 
+		/* damage evolution law */
+		static Real funcG(const Real& kappaD, const Real& epsCrackOnset, const Real& epsFracture, const bool& neverDamage, const int& damLaw);
+		static Real funcGDKappa(const Real& kappaD, const Real& epsCrackOnset, const Real& epsFracture, const bool& neverDamage, const int& damLaw);
+		/* inverse damage evolution law */
+		static Real funcGInv(const Real& omega, const Real& epsCrackOnset, const Real& epsFracture, const bool& neverDamage, const int& damLaw);
+		void setDamage(Real dmg);
+		void setRelResidualStrength(Real r);
+
 		virtual ~CpmPhys();
-		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(CpmPhys,NormShearPhys,"Representation of a single interaction of the Cpm type: storage for relevant parameters.\n\n Evolution of the contact is governed by :yref:`Law2_Dem3DofGeom_CpmPhys_Cpm` or :yref:`Law2_ScGeom_CpmPhys_Cpm`, that includes damage effects and chages of parameters inside CpmPhys. See :yref:`cpm-model<CpmMat>` for details.",
+		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(CpmPhys,NormShearPhys,"Representation of a single interaction of the Cpm type: storage for relevant parameters.\n\n Evolution of the contact is governed by :yref:`Law2_ScGeom_CpmPhys_Cpm`, that includes damage effects and chages of parameters inside CpmPhys. See :yref:`cpm-model<CpmMat>` for details.",
 			((Real,E,NaN,,"normal modulus (stiffness / crossSection) [Pa]"))
 			((Real,G,NaN,,"shear modulus [Pa]"))
 			((Real,tanFrictionAngle,NaN,,"tangens of internal friction angle [-]"))
@@ -157,7 +164,6 @@
 			((Real,refLength,NaN,,"initial length of interaction [m]"))
 			((Real,refPD,NaN,,"initial penetration depth of interaction [m] (used with ScGeom)"))
 			((Real,epsCrackOnset,NaN,,"strain at which the material starts to behave non-linearly"))
-			((Real,crackOpening,NaN,,"Crack opening (extansion of the bond) when the bond is fully broken in tension. [m]"))
 			((Real,relDuctility,NaN,,"Relative ductility of bonds in normal direction"))
 			((Real,epsFracture,NaN,,"strain at which the bond is fully broken [-]"))
 			((Real,dmgTau,-1,,"characteristic time for damage (if non-positive, the law without rate-dependence is used)"))
@@ -170,11 +176,11 @@
 			((Real,kappaD,0,,"Up to now maximum normal strain (semi-norm), non-decreasing in time."))
 			((Real,epsNPl,0,,"normal plastic strain (initially zero)"))
 			((bool,neverDamage,false,,"the damage evolution function will always return virgin state"))
-			((int,damLaw,-1,,"Law for softening part of uniaxial tension. 0 for linear, 1 for exponential (default)"))
+			((int,damLaw,1,,"Law for softening part of uniaxial tension. 0 for linear, 1 for exponential (default)"))
 			((Real,epsTrans,0,,"Transversal strain (perpendicular to the contact axis)"))
 			//((Real,epsPlSum,0,,"cummulative shear plastic strain measure (scalar) on this contact"))
 			((bool,isCohesive,false,,"if not cohesive, interaction is deleted when distance is greater than zero."))
-			((Vector3r,epsT,Vector3r::Zero(),,"Total shear strain (either computed from increments with :yref:`ScGeom` or simple copied with :yref:`Dem3DofGeom`) |yupdate|"))
+			((Vector3r,epsT,Vector3r::Zero(),,"Total shear strain (either computed from increments with :yref:`ScGeom`) |yupdate|"))
 			,
 			createIndex(); epsT=Fs=Vector3r::Zero(); Fn=0; omega=0;
 			,
@@ -187,6 +193,12 @@
 			.def_readonly("relResidualStrength",&CpmPhys::relResidualStrength,"Relative residual strength")
 			.def_readonly("cummBetaIter",&CpmPhys::cummBetaIter,"Cummulative number of iterations inside CpmMat::solveBeta (for debugging).")
 			.def_readonly("cummBetaCount",&CpmPhys::cummBetaCount,"Cummulative number of calls of CpmMat::solveBeta (for debugging).")
+			.def("funcG",&CpmPhys::funcG,(py::arg("kappaD"),py::arg("epsCrackOnset"),py::arg("epsFracture"),py::arg("neverDamage")=false,py::arg("damLaw")=1),"Damage evolution law, evaluating the $\\omega$ parameter. $\\kappa_D$ is historically maximum strain, *epsCrackOnset* ($\\varepsilon_0$) = :yref:`CpmPhys.epsCrackOnset`, *epsFracture* = :yref:`CpmPhys.epsFracture`; if *neverDamage* is ``True``, the value returned will always be 0 (no damage). TODO")
+			.staticmethod("funcG")
+			.def("funcGInv",&CpmPhys::funcGInv,(py::arg("omega"),py::arg("epsCrackOnset"),py::arg("epsFracture"),py::arg("neverDamage")=false,py::arg("damLaw")=1),"Inversion of damage evolution law, evaluating the $\\kappa_D$ parameter. $\\omega$ is damage, for other parameters see funcG function")
+			.staticmethod("funcGInv")
+			.def("setDamage",&CpmPhys::setDamage,"TODO")
+			.def("setRelResidualStrength",&CpmPhys::setRelResidualStrength,"TODO")
 		);
 	DECLARE_LOGGER;
 	REGISTER_CLASS_INDEX(CpmPhys,NormShearPhys);
@@ -236,19 +248,9 @@
 *
 *********************************************************************************/
 
-class Law2_SomeGeom_CpmPhys_Cpm: public LawFunctor{
+class Law2_ScGeom_CpmPhys_Cpm: public LawFunctor{
 	public:
-	/*! Damage evolution law */
-	static Real funcG(const Real& kappaD, const Real& epsCrackOnset, const Real& epsFracture, const bool& neverDamage, const int& damLaw) {
-		if (kappaD<epsCrackOnset || neverDamage) return 0;
-		switch (damLaw) {
-			case 0: // linear
-				return (1.-epsCrackOnset/kappaD)/(1.-epsCrackOnset/epsFracture);
-			case 1: // exponential
-				return 1.-(epsCrackOnset/kappaD)*exp(-(kappaD-epsCrackOnset)/epsFracture);
-		}
-		return 0;
-	}
+	void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I);
 
 	Real yieldSigmaTMagnitude(Real sigmaN, Real omega, Real undamagedCohesion, Real tanFrictionAngle) {
 #ifdef CPM_MATERIAL_MODEL
@@ -262,7 +264,7 @@
 	//void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I);
 
 	FUNCTOR2D(GenericSpheresContact,CpmPhys);
-	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_SomeGeom_CpmPhys_Cpm,LawFunctor,"Constitutive law for the :yref:`cpm-model<CpmMat>`.",
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGeom_CpmPhys_Cpm,LawFunctor,"Constitutive law for the :yref:`cpm-model<CpmMat>`.",
 		((int,yieldSurfType,2,,"yield function: 0: mohr-coulomb (original); 1: parabolic; 2: logarithmic, 3: log+lin_tension, 4: elliptic, 5: elliptic+log"))
 		((Real,yieldLogSpeed,.1,,"scaling in the logarithmic yield surface (should be <1 for realistic results; >=0 for meaningful results)"))
 		((Real,yieldEllipseShift,NaN,,"horizontal scaling of the ellipse (shifts on the +x axis as interactions with +y are given)"))
@@ -270,40 +272,7 @@
 		((Real,epsSoft,((void)"approximates confinement -20MPa precisely, -100MPa a little over, -200 and -400 are OK (secant)",-3e-3),,"Strain at which softening in compression starts (non-negative to deactivate)"))
 		((Real,relKnSoft,.3,,"Relative rigidity of the softening branch in compression (0=perfect elastic-plastic, <0 softening, >0 hardening)")),
 		/*ctor*/,
-		.def("funcG",&Law2_SomeGeom_CpmPhys_Cpm::funcG,(py::arg("kappaD"),py::arg("epsCrackOnset"),py::arg("epsFracture"),py::arg("neverDamage")=false,py::arg("damLaw")=1),"Damage evolution law, evaluating the $\\omega$ parameter. $\\kappa_D$ is historically maximum strain, *epsCrackOnset* ($\\varepsilon_0$) = :yref:`CpmPhys.epsCrackOnset`, *epsFracture* = :yref:`CpmPhys.epsFracture`; if *neverDamage* is ``True``, the value returned will always be 0 (no damage). TODO")
-		.def("yieldSigmaTMagnitude",&Law2_SomeGeom_CpmPhys_Cpm::yieldSigmaTMagnitude,(py::arg("sigmaN"),py::arg("omega"),py::arg("undamagedCohesion"),py::arg("tanFrictionAngle")),"Return radius of yield surface for given material and state parameters; uses attributes of the current instance (*yieldSurfType* etc), change them before calling if you need that.")
-	);
-	DECLARE_LOGGER;
-};
-REGISTER_SERIALIZABLE(Law2_SomeGeom_CpmPhys_Cpm);
-
-
-
-
-class Law2_Dem3DofGeom_CpmPhys_Cpm: public Law2_SomeGeom_CpmPhys_Cpm{
-	public:
-	void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I);
-
-	FUNCTOR2D(Dem3DofGeom,CpmPhys);
-	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_Dem3DofGeom_CpmPhys_Cpm,Law2_SomeGeom_CpmPhys_Cpm,"Constitutive law for the :yref:`cpm-model<CpmMat>`.",
-		,
-		/*ctor*/,
-	);
-	DECLARE_LOGGER;
-};
-REGISTER_SERIALIZABLE(Law2_Dem3DofGeom_CpmPhys_Cpm);
-
-
-
-
-class Law2_ScGeom_CpmPhys_Cpm: public Law2_SomeGeom_CpmPhys_Cpm{
-	public:
-	void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I);
-
-	FUNCTOR2D(ScGeom,CpmPhys);
-	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGeom_CpmPhys_Cpm,Law2_SomeGeom_CpmPhys_Cpm,"Constitutive law for the :yref:`cpm-model<CpmMat>`.",
-		,
-		/*ctor*/,
+		.def("yieldSigmaTMagnitude",&Law2_ScGeom_CpmPhys_Cpm::yieldSigmaTMagnitude,(py::arg("sigmaN"),py::arg("omega"),py::arg("undamagedCohesion"),py::arg("tanFrictionAngle")),"Return radius of yield surface for given material and state parameters; uses attributes of the current instance (*yieldSurfType* etc), change them before calling if you need that.")
 	);
 	DECLARE_LOGGER;
 };
@@ -325,7 +294,6 @@
 *
 *********************************************************************************/
 
-
 #ifdef YADE_OPENGL
 	#include<yade/pkg/common/GLDrawFunctors.hpp>
 	class Gl1_CpmPhys: public GlIPhysFunctor {

=== modified file 'pkg/dem/DomainLimiter.cpp'
--- pkg/dem/DomainLimiter.cpp	2012-04-13 17:38:47 +0000
+++ pkg/dem/DomainLimiter.cpp	2013-03-07 18:28:01 +0000
@@ -46,8 +46,8 @@
 	_path.clear(); _path.push_back(Vector6r::Zero());
 	for(size_t i=0; i<pathSize; i++) {
 		Vector6r pt;
-		pt.start<3>()=Vector3r(i<disPath.size()?disPath[i]:(disPath.empty()?Vector3r::Zero():*(disPath.rbegin())));
-		pt.end<3>()=Vector3r(i<rotPath.size()?rotPath[i]:(rotPath.empty()?Vector3r::Zero():*(rotPath.rbegin())));
+		pt.head<3>()=Vector3r(i<disPath.size()?disPath[i]:(disPath.empty()?Vector3r::Zero():*(disPath.rbegin())));
+		pt.tail<3>()=Vector3r(i<rotPath.size()?rotPath[i]:(rotPath.empty()?Vector3r::Zero():*(rotPath.rbegin())));
 		_path.push_back(pt);
 
 	}
@@ -106,7 +106,7 @@
 		return;
 	}
 	/* initialize or update local axes and trsf */
-	uGeom.end<3>()=Vector3r(NaN,NaN,NaN);
+	uGeom.tail<3>()=Vector3r(NaN,NaN,NaN);
 	if(!l3Geom){ // IGeom's that don't have local axes
 		axX=gsc->normal; /* just in case */ axX.normalize();
 		if(doInit){ // initialization of the new interaction -- define local axes
@@ -115,14 +115,14 @@
 			axY.normalize();
 			axZ=axX.cross(axY);
 			LOG_DEBUG("Initial axes x="<<axX<<", y="<<axY<<", z="<<axZ);
-			if(scGeom6d) uGeom.end<3>()=Vector3r::Zero();
+			if(scGeom6d) uGeom.tail<3>()=Vector3r::Zero();
 		} else { // udpate of an existing interaction
 			if(scGeom){
 				scGeom->rotate(axY); scGeom->rotate(axZ);
 				scGeom->rotate(shearTot);
 				shearTot+=scGeom->shearIncrement();
-				uGeom.start<3>()=Vector3r(-scGeom->penetrationDepth,shearTot.dot(axY),shearTot.dot(axZ));
-				if(scGeom6d) uGeom.end<3>()=-1.*Vector3r(scGeom6d->getTwist(),scGeom6d->getBending().dot(axY),scGeom6d->getBending().dot(axZ));
+				uGeom.head<3>()=Vector3r(-scGeom->penetrationDepth,shearTot.dot(axY),shearTot.dot(axZ));
+				if(scGeom6d) uGeom.tail<3>()=-1.*Vector3r(scGeom6d->getTwist(),scGeom6d->getBending().dot(axY),scGeom6d->getBending().dot(axZ));
 			}
 			else{ // d3dGeom
 				throw runtime_error("LawTester: Dem3DofGeom not yet supported.");
@@ -136,8 +136,8 @@
 	} else {
 		trsf=Matrix3r(l3Geom->trsf);
 		axX=trsf.row(0); axY=trsf.row(1); axZ=trsf.row(2);
-		uGeom.start<3>()=l3Geom->u;
-		if(l6Geom) uGeom.end<3>()=l6Geom->phi;
+		uGeom.head<3>()=l3Geom->u;
+		if(l6Geom) uGeom.tail<3>()=l6Geom->phi;
 	}
 	// perform all shearing by translation, as it does not induce bending
 	if(hasRot && rotWeight!=0){ LOG_INFO("LawTester.rotWeight set to 0 (was "<<rotWeight<<"), since rotational DoFs are in use."); rotWeight=0; }
@@ -148,16 +148,16 @@
 	// here we go ahead, finally
 	Vector6r uu=linearInterpolate<Vector6r,int>(step,_pathT,_path,_interpPos);
 	Vector6r dUU=uu-uuPrev; uuPrev=uu;
-	Vector3r dU(dUU.start<3>()), dPhi(dUU.end<3>());
-	//Vector3r dU=u-uPrev.start<3>(); uPrev.start<3>()=u;
-	//Vector3r dPhi=phi-uPrev.end<3>(); uPrev.end<3>()=phi;
+	Vector3r dU(dUU.head<3>()), dPhi(dUU.tail<3>());
+	//Vector3r dU=u-uPrev.head<3>(); uPrev.head<3>()=u;
+	//Vector3r dPhi=phi-uPrev.tail<3>(); uPrev.tail<3>()=phi;
 	if(displIsRel){
 		LOG_DEBUG("Relative displacement diff is "<<dU<<" (will be normalized by "<<gsc->refR1+gsc->refR2<<")");
 		dU*=refLength;
 	}
 	LOG_DEBUG("Absolute diff is: displacement "<<dU<<", rotation "<<dPhi);
 	uTest=uTestNext; // the value that was next in the previous step is the current one now
-	uTestNext.start<3>()+=dU; uTestNext.end<3>()+=dPhi;
+	uTestNext.head<3>()+=dU; uTestNext.tail<3>()+=dPhi;
 
 	// reset velocities where displacement is controlled
 	//for(int i=0; i<3; i++){ if(forceControl[i]==0){ state1.vel[i]=0; state2.vel[i]=0; }
@@ -282,7 +282,7 @@
 
 	// find maximum displacement, draw axes in the shear plane
 	Real displMax=0;
-	FOREACH(const Vector6r& v, VV) displMax=max(v.start<3>().squaredNorm(),displMax);
+	FOREACH(const Vector6r& v, VV) displMax=max(v.head<3>().squaredNorm(),displMax);
 	displMax=1.2*scale*sqrt(displMax);
 
 	glLineWidth(1.);
@@ -294,7 +294,7 @@
 	for(size_t segment=0; segment<numSegments-1; segment++){
 		// different colors before and after the current point
 		Real t0=TT[segment],t1=TT[segment+1];
-		const Vector3r &from=-VV[segment].start<3>()*scale, &to=-VV[segment+1].start<3>()*scale;
+		const Vector3r &from=-VV[segment].head<3>()*scale, &to=-VV[segment+1].head<3>()*scale;
 		// current segment
 		if(t>t0 && t<t1){
 			Real norm=(t-t0)/(t1-t0);

=== modified file 'pkg/dem/DomainLimiter.hpp'
--- pkg/dem/DomainLimiter.hpp	2012-01-10 09:39:47 +0000
+++ pkg/dem/DomainLimiter.hpp	2013-03-07 18:28:01 +0000
@@ -24,8 +24,8 @@
 		virtual void action();
 		void postLoad(LawTester&);
 		void warnDeprec(const string& s1, const string& s2){ if(!warnedDeprecPtRot){ warnedDeprecPtRot=true; LOG_WARN("LawTester."<<s1<<" is deprecated, use LawTester."<<s2<<" instead.");} }
-		Vector3r get_ptOurs(){ warnDeprec("ptOurs","uTest.head()"); return uTest.start<3>(); } Vector3r get_ptGeom(){ warnDeprec("ptGeom","uGeom.head()"); return uGeom.start<3>(); }
-		Vector3r get_rotOurs(){ warnDeprec("rotOurs","uTest.tail()"); return uTest.end<3>(); }  Vector3r get_rotGeom(){ warnDeprec("rotGeom","uGeom.tail()"); return uGeom.end<3>(); }
+		Vector3r get_ptOurs(){ warnDeprec("ptOurs","uTest.head()"); return uTest.head<3>(); } Vector3r get_ptGeom(){ warnDeprec("ptGeom","uGeom.head()"); return uGeom.head<3>(); }
+		Vector3r get_rotOurs(){ warnDeprec("rotOurs","uTest.tail()"); return uTest.tail<3>(); }  Vector3r get_rotGeom(){ warnDeprec("rotGeom","uGeom.tail()"); return uGeom.tail<3>(); }
 	DECLARE_LOGGER;
 	YADE_CLASS_BASE_DOC_ATTRS_DEPREC_INIT_CTOR_PY(LawTester,PartialEngine,"Prescribe and apply deformations of an interaction in terms of local normal and shear displacements and rotations (using either :yref:`disPpath<LawTester.disPath>` and :yref:`rotPath<LawTester.rotPath>` [or :yref:`path<LawTester.path>` in the future]). Supported :yref:`IGeom` types are :yref:`ScGeom`, :yref:`L3Geom` and :yref:`L6Geom`. \n\nSee :ysrc:`scripts/test/law-test.py` for an example.",
 		((vector<Vector3r>,disPath,,Attr::triggerPostLoad,"Loading path, where each Vector3 contains desired normal displacement and two components of the shear displacement (in local coordinate system, which is being tracked automatically. If shorter than :yref:`rotPath<LawTester.rotPath>`, the last value is repeated."))

=== modified file 'pkg/dem/ElasticContactLaw.cpp'
--- pkg/dem/ElasticContactLaw.cpp	2012-06-28 19:34:29 +0000
+++ pkg/dem/ElasticContactLaw.cpp	2013-03-06 17:30:45 +0000
@@ -52,7 +52,7 @@
 	ScGeom*    geom= static_cast<ScGeom*>(ig.get());
 	FrictPhys* phys = static_cast<FrictPhys*>(ip.get());
 	if(geom->penetrationDepth <0){
-		if (unlikely(neverErase)) {
+		if (neverErase) {
 			phys->shearForce = Vector3r::Zero();
 			phys->normalForce = Vector3r::Zero();}
 		else 	scene->interactions->requestErase(contact);
@@ -65,7 +65,7 @@
 	shearForce -= phys->ks*shearDisp;
 	Real maxFs = phys->normalForce.squaredNorm()*std::pow(phys->tangensOfFrictionAngle,2);
 
-	if (likely(!scene->trackEnergy  && !traceEnergy)){//Update force but don't compute energy terms (see below))
+	if (!scene->trackEnergy  && !traceEnergy){//Update force but don't compute energy terms (see below))
 		// PFC3d SlipModel, is using friction angle. CoulombCriterion
 		if( shearForce.squaredNorm() > maxFs ){
 			Real ratio = sqrt(maxFs) / shearForce.norm();

=== modified file 'pkg/dem/ElasticContactLaw.hpp'
--- pkg/dem/ElasticContactLaw.hpp	2012-06-28 19:34:29 +0000
+++ pkg/dem/ElasticContactLaw.hpp	2013-01-14 21:20:06 +0000
@@ -42,7 +42,7 @@
 class Law2_ScGeom_ViscoFrictPhys_CundallStrack: public Law2_ScGeom_FrictPhys_CundallStrack{
 	public:
 		virtual void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I);
-		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGeom_ViscoFrictPhys_CundallStrack,Law2_ScGeom_FrictPhys_CundallStrack,"Law for linear compression, and Mohr-Coulomb plasticity surface without cohesion.\nThis law implements the classical linear elastic-plastic law from [CundallStrack1979]_ (see also [Pfc3dManual30]_). The normal force is (with the convention of positive tensile forces) $F_n=\\min(k_n u_n, 0)$. The shear force is $F_s=k_s u_s$, the plasticity condition defines the maximum value of the shear force : $F_s^{\\max}=F_n\\tan(\\phi)$, with $\\phi$ the friction angle.\n\nThis law is well tested in the context of triaxial simulation, and has been used for a number of published results (see e.g. [Scholtes2009b]_ and other papers from the same authors). It is generalised by :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`, which adds cohesion and moments at contact.",
+		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGeom_ViscoFrictPhys_CundallStrack,Law2_ScGeom_FrictPhys_CundallStrack,"Law similar to :yref:`Law2_ScGeom_FrictPhys_CundallStrack` with the addition of shear creep at contacts.",
 		((bool,shearCreep,false,," "))
 		((Real,viscosity,1,," "))
 		((Real,creepStiffness,1,," "))

=== modified file 'pkg/dem/FlowEngine.cpp'
--- pkg/dem/FlowEngine.cpp	2012-11-26 10:51:33 +0000
+++ pkg/dem/FlowEngine.cpp	2013-05-06 15:50:31 +0000
@@ -1,6 +1,7 @@
 /*************************************************************************
-*  Copyright (C) 2009 by Emanuele Catalano                               *
-*  emanuele.catalano@xxxxxxxxxxx                                         *
+*  Copyright (C) 2009 by Emanuele Catalano <catalano@xxxxxxxxxxxxxxx>    *
+*  Copyright (C) 2009 by Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>     *
+*  Copyright (C) 2012 by Donia Marzougui <donia.marzougui@xxxxxxxxxxxxxxx>*
 *                                                                        *
 *  This program is free software; it is licensed under the terms of the  *
 *  GNU General Public License v2 or later. See file LICENSE for details. *
@@ -68,22 +69,21 @@
 
 
         ///Compute flow and and forces here
-
-	solver->GaussSeidel(scene->dt);
-        timingDeltas->checkpoint ( "Gauss-Seidel (includes matrix construct and factorization in single-thread mode)" );
-        if ( save_mgpost ) solver->MGPost();
-        solver->ComputeFacetForcesWithCache();
+	if (pressureForce){
+		solver->GaussSeidel(scene->dt);
+		timingDeltas->checkpoint ( "Gauss-Seidel (includes matrix construct and factorization in single-thread mode)" );
+		solver->ComputeFacetForcesWithCache();}
         timingDeltas->checkpoint ( "Compute_Forces" );
         ///Application of vicscous forces
         scene->forces.sync();
 	timingDeltas->checkpoint ( "forces.sync()" );
-	if ( viscousShear ) ApplyViscousForces ( *solver );
+	ComputeViscousForces ( *solver );
 	timingDeltas->checkpoint ( "viscous forces" );
 	Vector3r force;
         Finite_vertices_iterator vertices_end = solver->T[solver->currentTes].Triangulation().finite_vertices_end();
         for ( Finite_vertices_iterator V_it = solver->T[solver->currentTes].Triangulation().finite_vertices_begin(); V_it !=  vertices_end; V_it++ ) {
-		force = Vector3r ( ( V_it->info().forces ) [0],V_it->info().forces[1],V_it->info().forces[2] );
-                if (viscousShear){
+		force = pressureForce ? Vector3r ( V_it->info().forces[0],V_it->info().forces[1],V_it->info().forces[2] ): Vector3r(0,0,0);
+                if (viscousShear || shearLubrication){
 			force = force + solver->viscousShearForces[V_it->info().id()];
 			scene->forces.addTorque ( V_it->info().id(), solver->viscousShearTorques[V_it->info().id()]);
 		}
@@ -118,7 +118,7 @@
 			workerThread.detach();
 			if (Debug) cerr<<"backgrounded"<<endl;
 			Initialize_volumes(solver);
-			if (viscousShear) ApplyViscousForces(*solver);
+			ComputeViscousForces(*solver);
 			if (Debug) cerr<<"volumes initialized"<<endl;
 		}
 		else {
@@ -129,7 +129,7 @@
 	        if (Update_Triangulation && !first) {
 			Build_Triangulation (P_zero, solver);
 			Initialize_volumes(solver);
-			if (viscousShear) ApplyViscousForces(*solver);
+			ComputeViscousForces(*solver);
                		Update_Triangulation = false;}
         }
         if ( velocity_profile ) /*flow->FluidVelocityProfile();*/solver->Average_Fluid_Velocity();
@@ -288,8 +288,7 @@
         if ( !first && !multithread && (useSolver==0 || fluidBulkModulus>0)) flow->Interpolate ( flow->T[!flow->currentTes], flow->T[flow->currentTes] );
         if ( WaveAction ) flow->ApplySinusoidalPressure ( flow->T[flow->currentTes].Triangulation(), Sinus_Amplitude, Sinus_Average, 30 );
 
-        if ( viscousShear ) flow->ComputeEdgesSurfaces();
-	if ( normalLubrication ) flow->ComputeEdgesSurfaces();
+        if ( viscousShear || normalLubrication || shearLubrication) flow->computeEdgesSurfaces();
 }
 
 void FlowEngine::setPositionsBuffer(bool current)
@@ -300,7 +299,7 @@
 	shared_ptr<Sphere> sph ( new Sphere );
         const int Sph_Index = sph->getClassIndexStatic();
 	FOREACH ( const shared_ptr<Body>& b, *scene->bodies ) {
-                if (!b || (unlikely(ignoredBody>=0) && ignoredBody==b->getId())) continue;
+                if (!b || ignoredBody==b->getId()) continue;
                 posData& dat = buffer[b->getId()];
 		dat.id=b->getId();
 		dat.pos=b->state->pos;
@@ -640,86 +639,117 @@
         return volume;
 }
 template<class Solver>
-void FlowEngine::ApplyViscousForces ( Solver& flow )
+void FlowEngine::ComputeViscousForces ( Solver& flow )
 {
+	if (viscousShear || normalLubrication || shearLubrication){
 //   flow->ComputeEdgesSurfaces(); //only done in buildTriangulation
-        if ( Debug ) cout << "Application of viscous forces" << endl;
-        if ( Debug ) cout << "Number of edges = " << flow.Edge_ids.size() << endl;
-        for ( unsigned int k=0; k<flow.viscousShearForces.size(); k++ ) flow.viscousShearForces[k]=Vector3r::Zero();
-	for ( unsigned int k=0; k<flow.viscousShearTorques.size(); k++ ) flow.viscousShearTorques[k]=Vector3r::Zero();
-	for ( unsigned int k=0; k<flow.viscousBodyStress.size(); k++) flow.viscousBodyStress[k]=Matrix3r::Zero();
-	for ( unsigned int k=0; k<flow.normLubForce.size(); k++ ) flow.normLubForce[k]=Vector3r::Zero();
-	for ( unsigned int k=0; k<flow.lubBodyStress.size(); k++) flow.lubBodyStress[k]=Matrix3r::Zero();
-
-	typedef typename Solver::Tesselation Tesselation;
-        const Tesselation& Tes = flow.T[flow.currentTes];
-
-        for ( int i=0; i< ( int ) flow.Edge_ids.size(); i++ ) {
-                int hasFictious= Tes.vertex ( flow.Edge_ids[i].first )->info().isFictious +  Tes.vertex ( flow.Edge_ids[i].second )->info().isFictious;
-		const shared_ptr<Body>& sph1 = Body::byId ( flow.Edge_ids[i].first, scene );
-                const shared_ptr<Body>& sph2 = Body::byId ( flow.Edge_ids[i].second, scene );
-                Sphere* s1=YADE_CAST<Sphere*> ( sph1->shape.get() );
-                Sphere* s2=YADE_CAST<Sphere*> ( sph2->shape.get() );
-		Vector3r deltaV; Real deltaNormV; Vector3r deltaShearV;
-		Vector3r normal = sph1->state->pos + makeVector3r(Tes.vertex(flow.Edge_ids[i].first)->info().ghostShift())
-			- sph2->state->pos - makeVector3r(Tes.vertex(flow.Edge_ids[i].second)->info().ghostShift());
-		Real dist = normal.norm();
-		normal*= (1./dist);
-		dist = dist - s2->radius - s1->radius;
-
-		Vector3r visc_f; Vector3r lub_f;
+		if ( Debug ) cout << "Application of viscous forces" << endl;
+		if ( Debug ) cout << "Number of edges = " << flow.Edge_ids.size() << endl;
+		for ( unsigned int k=0; k<flow.viscousShearForces.size(); k++ ) flow.viscousShearForces[k]=Vector3r::Zero();
+		for ( unsigned int k=0; k<flow.viscousShearTorques.size(); k++ ) flow.viscousShearTorques[k]=Vector3r::Zero();
+		for ( unsigned int k=0; k<flow.viscousBodyStress.size(); k++) flow.viscousBodyStress[k]=Matrix3r::Zero();
+		for ( unsigned int k=0; k<flow.normLubForce.size(); k++ ) flow.normLubForce[k]=Vector3r::Zero();
+		for ( unsigned int k=0; k<flow.lubBodyStress.size(); k++) flow.lubBodyStress[k]=Matrix3r::Zero();
+
+		typedef typename Solver::Tesselation Tesselation;
+		const Tesselation& Tes = flow.T[flow.currentTes];
+
+		for ( int i=0; i< ( int ) flow.Edge_ids.size(); i++ ) {
+			const int& id1 = flow.Edge_ids[i].first;
+			const int& id2 = flow.Edge_ids[i].second;
+			
+			int hasFictious= Tes.vertex ( id1 )->info().isFictious +  Tes.vertex ( id2 )->info().isFictious;
+// 			if (hasFictious==2) continue;
+			if (hasFictious>0 or id1==id2) continue;
+			const shared_ptr<Body>& sph1 = Body::byId ( id1, scene );
+			const shared_ptr<Body>& sph2 = Body::byId ( id2, scene );
+			Sphere* s1=YADE_CAST<Sphere*> ( sph1->shape.get() );
+			Sphere* s2=YADE_CAST<Sphere*> ( sph2->shape.get() );
+			const Real& r1 = s1->radius;
+			const Real& r2 = s2->radius;
+			Vector3r deltaV; Real deltaNormV; Vector3r deltaShearV;
+			Vector3r O1O2_vect; Real O1O2; Vector3r normal; Real surfaceDist; Vector3r O1C_vect; Vector3r O2C_vect;Real meanRad ;Real Rh;
+			Vector3r visc_f; Vector3r lub_f;
 		//FIXME: if periodic and velGrad!=0, then deltaV should account for velGrad, not the case currently
-                if ( !hasFictious )
-                        deltaV = (sph2->state->vel + sph2->state->angVel.cross(s2->radius * flow.Edge_normal[i])) - (sph1->state->vel+ sph1->state->angVel.cross(s1->radius * flow.Edge_normal[i]));
-                else {
-                        if ( hasFictious==1 ) {//for the fictious sphere, use velocity of the boundary, not of the body
-                                Vector3r v1 = ( Tes.vertex ( flow.Edge_ids[i].first )->info().isFictious ) ? flow.boundary ( flow.Edge_ids[i].first ).velocity:sph1->state->vel + sph1->state->angVel.cross(s1->radius * flow.Edge_normal[i]);
-                                Vector3r v2 = ( Tes.vertex ( flow.Edge_ids[i].second )->info().isFictious ) ? flow.boundary ( flow.Edge_ids[i].second ).velocity:sph2->state->vel + sph2->state->angVel.cross(s2->radius * (-flow.Edge_normal[i]));
-                                deltaV = v2-v1;
-                        } else {//both fictious, ignore
-                                deltaV = Vector3r::Zero();
-                        }
-                }
-                deltaShearV = deltaV - ( flow.Edge_normal[i].dot ( deltaV ) ) *flow.Edge_normal[i];
-		if (shearLubrication)
-			visc_f = flow.ComputeShearLubricationForce (deltaShearV,i,eps);
-		else
-			visc_f = flow.ComputeViscousForce ( deltaShearV, i );
+			if ( !hasFictious ){
+				O1O2_vect = sph2->state->pos + makeVector3r(Tes.vertex(id2)->info().ghostShift()) - sph1->state->pos - makeVector3r(Tes.vertex(id1)->info().ghostShift());
+				O1O2 = O1O2_vect.norm(); 
+				normal= (O1O2_vect/O1O2);
+				surfaceDist = O1O2 - r2 - r1;
+				O1C_vect = (O1O2/2. + (pow(r1,2) - pow(r2,2)) / (2.*O1O2))*normal;
+				O2C_vect = -(O1O2_vect-O1C_vect);
+				meanRad = (r2 + r1)/2.;
+				Rh = (r1 < r2)? surfaceDist + 0.45 * r1 : surfaceDist + 0.45 * r2;
+				deltaV = (sph2->state->vel + sph2->state->angVel.cross(-r2 * normal)) - (sph1->state->vel+ sph1->state->angVel.cross(r1 * normal));
+
+			} else {
+				if ( hasFictious==1 ) {//for the fictious sphere, use velocity of the boundary, not of the body
+					bool v1fictious = Tes.vertex ( id1 )->info().isFictious;
+					int bnd = v1fictious? id1 : id2;
+					int coord = flow.boundary(bnd).coordinate;
+					O1O2 = v1fictious ? abs((sph2->state->pos + makeVector3r(Tes.vertex(id2)->info().ghostShift()))[coord] - flow.boundary(bnd).p[coord]) : abs((sph1->state->pos + makeVector3r(Tes.vertex(id1)->info().ghostShift()))[coord] - flow.boundary(bnd).p[coord]);
+					if(v1fictious)
+						normal = makeVector3r(flow.boundary(id1).normal);
+					else
+						normal = -makeVector3r(flow.boundary(id2).normal);
+					O1O2_vect = O1O2 * normal;
+					meanRad = v1fictious ? r2:r1;
+					surfaceDist = O1O2- meanRad;
+					if (v1fictious){
+						O1C_vect = Vector3r::Zero();
+						O2C_vect = -O1O2_vect;}
+					else{
+						O1C_vect =  O1O2_vect;
+						O2C_vect = Vector3r::Zero();}
 				
-//                 if ( Debug ) cout << "la force visqueuse entre " << flow->Edge_ids[i].first << " et " << flow->Edge_ids[i].second << "est " << visc_f << endl;
-
-///    //(1) directement sur le body Yade...
-//     scene->forces.addForce(flow->Edge_ids[i].first,visc_f);
-//     scene->forces.addForce(flow->Edge_ids[i].second,-visc_f);
-
-///   //(2) ou dans CGAL? On a le choix (on pourrait même avoir info->viscousF pour faire la différence entre les deux types de forces... mais ça prend un peu plus de mémoire et de temps de calcul)
-//     Tes.vertex(flow->Edge_ids[i].first)->info().forces=Tes.vertex(flow->Edge_ids[i].first)->info().forces+makeCgVect(visc_f);
-//     Tes.vertex(flow->Edge_ids[i].second)->info().forces=Tes.vertex(flow->Edge_ids[i].second)->info().forces+makeCgVect(visc_f);
-
-/// //(3) ou dans un vecteur séparé (rapide)
-		flow.viscousShearForces[flow.Edge_ids[i].first]+=visc_f;
-		flow.viscousShearForces[flow.Edge_ids[i].second]-=visc_f;
-		flow.viscousShearTorques[flow.Edge_ids[i].first]+=flow.Edge_force_point[i].cross(visc_f);
-		flow.viscousShearTorques[flow.Edge_ids[i].second]-=(flow.Edge_centerDistVect[i]-flow.Edge_force_point[i]).cross(visc_f);
-		
-/// Compute the viscous shear stress on each particle
-		flow.viscousBodyStress[flow.Edge_ids[i].first] += visc_f * flow.Edge_force_point[i].transpose();
-		flow.viscousBodyStress[flow.Edge_ids[i].second] -= visc_f * (flow.Edge_centerDistVect[i]-flow.Edge_force_point[i]).transpose();		
-		
-/// Compute the normal lubrication force applied on each particle
-		if (normalLubrication){
-			deltaNormV = normal.dot(deltaV);
-// 			deltaNormV = (flow.Edge_normal[i].dot (deltaV)) * flow.Edge_normal[i];
-			lub_f = flow.ComputeNormalLubricationForce (deltaNormV, dist, i,eps,5000.,scene->dt)*normal;
-			flow.normLubForce[flow.Edge_ids[i].first]+=lub_f;
-			flow.normLubForce[flow.Edge_ids[i].second]-=lub_f;
-		
-/// Compute the normal lubrication stress on each particle
-			flow.lubBodyStress[flow.Edge_ids[i].first] += lub_f * flow.Edge_force_point[i].transpose();
-			flow.lubBodyStress[flow.Edge_ids[i].second] -= lub_f *(flow.Edge_centerDistVect[i]-flow.Edge_force_point[i]).transpose();
+					Rh = surfaceDist + 0.45 * meanRad;
+					Vector3r v1 = ( Tes.vertex ( id1 )->info().isFictious ) ? flow.boundary ( id1 ).velocity:sph1->state->vel + sph1->state->angVel.cross(r1 * normal);
+					Vector3r v2 = ( Tes.vertex ( id2 )->info().isFictious ) ? flow.boundary ( id2 ).velocity:sph2->state->vel + sph2->state->angVel.cross(-r2 * (normal));
+					deltaV = v2-v1;
+				}
+			}
+			deltaShearV = deltaV - ( normal.dot ( deltaV ) ) *normal;
+			
+			if (shearLubrication)
+				visc_f = flow.computeShearLubricationForce(deltaShearV,surfaceDist,i,eps,O1O2,meanRad);
+			else if (viscousShear) 
+				visc_f = flow.computeViscousShearForce ( deltaShearV, i , Rh);
+		
+                if ( Debug ) cout << "la force visqueuse entre " << id1 << " et " << id2 << "est " << visc_f << endl;
+
+
+			if (viscousShear || shearLubrication){
+				flow.viscousShearForces[id1]+=visc_f;
+				flow.viscousShearForces[id2]+=(-visc_f);
+				flow.viscousShearTorques[id1]+=O1C_vect.cross(visc_f);
+				flow.viscousShearTorques[id2]+=O2C_vect.cross(-visc_f);
+		
+				/// Compute the viscous shear stress on each particle
+				if (viscousShearBodyStress){
+					flow.viscousBodyStress[id1] += visc_f * O1C_vect.transpose()/ (4.0/3.0 *3.14* pow(r1,3));
+					flow.viscousBodyStress[id2] += (-visc_f) * O2C_vect.transpose()/ (4.0/3.0 *3.14* pow(r2,3));}
+			}
+					
+					
+		
+			/// Compute the normal lubrication force applied on each particle
+			if (normalLubrication){
+				deltaNormV = normal.dot(deltaV);
+				lub_f = flow.computeNormalLubricationForce (deltaNormV, surfaceDist, i,eps,stiffness,scene->dt,meanRad)*normal;
+				flow.normLubForce[id1]+=lub_f;
+				flow.normLubForce[id2]+=(-lub_f);
+
+			/// Compute the normal lubrication stress on each particle
+				if (viscousNormalBodyStress){
+					flow.lubBodyStress[id1] += lub_f * O1C_vect.transpose()/ (4.0/3.0 *3.14* pow(r1,3));
+					flow.lubBodyStress[id2] += (-lub_f) *O2C_vect.transpose() / (4.0/3.0 *3.14* pow(r2,3));}
+			if ( Debug ) cout << "la force normale entre " << id1 << " et " << id2 << "est " << lub_f << endl;
+			}
+		
 		}
+	
+		if(Debug) cout<<"number of viscousShearForce"<<flow.viscousShearForces.size()<<endl;
 	}
-        if(Debug) cout<<"number of viscousShearForce"<<flow.viscousShearForces.size()<<endl;
 }
 
 YADE_PLUGIN ( ( FlowEngine ) );
@@ -740,8 +770,11 @@
 	if (first) {
 		if (multithread) setPositionsBuffer(false);
 		cachedCell= Cell(*(scene->cell));
-		Build_Triangulation(P_zero,solver); Initialize_volumes(solver); backgroundSolver=solver; backgroundCompleted=true;}
+		Build_Triangulation(P_zero,solver);
+		if (solver->errorCode>0) {LOG_INFO("triangulation error, pausing"); Omega::instance().pause(); return;}
+		Initialize_volumes(solver); backgroundSolver=solver; backgroundCompleted=true;}
 //         if ( first ) {Build_Triangulation ( P_zero ); Update_Triangulation = false; Initialize_volumes();}
+	
 	timingDeltas->checkpoint("Triangulating");
         UpdateVolumes (solver);
         Eps_Vol_Cumulative += eps_vol_max;
@@ -756,28 +789,28 @@
 	timingDeltas->checkpoint("Update_Volumes");
 
 	///Compute flow and and forces here
-
-	solver->GaussSeidel(scene->dt);
-	timingDeltas->checkpoint("Gauss-Seidel");
-	solver->ComputeFacetForcesWithCache();
+	if (pressureForce){
+		solver->GaussSeidel(scene->dt);
+		timingDeltas->checkpoint("Gauss-Seidel");
+		solver->ComputeFacetForcesWithCache();}
 	timingDeltas->checkpoint("Compute_Pressure_Forces");
 
         ///Compute vicscous forces
         scene->forces.sync();
-        if (viscousShear) ApplyViscousForces(*solver);
+        ComputeViscousForces(*solver);
 	timingDeltas->checkpoint("Compute_Viscous_Forces");
 	Vector3r force;
 	const Tesselation& Tes = solver->T[solver->currentTes];
 	for (int id=0; id<=Tes.max_id; id++){
 		assert (Tes.vertexHandles[id] != NULL);
 		const Tesselation::Vertex_Info& v_info = Tes.vertexHandles[id]->info();
-		force = Vector3r ( ( v_info.forces ) [0],v_info.forces[1],v_info.forces[2] );
+		force =(pressureForce) ? Vector3r ( ( v_info.forces ) [0],v_info.forces[1],v_info.forces[2] ) : Vector3r(0,0,0);
                 if (viscousShear){
 			force = force +solver->viscousShearForces[v_info.id()];
 			scene->forces.addTorque ( v_info.id(), solver->viscousShearTorques[v_info.id()]);
 		}
 		if (normalLubrication)
-			force = force - solver->normLubForce[v_info.id()];
+			force = force + solver->normLubForce[v_info.id()];
 		scene->forces.addForce ( v_info.id(), force);
 	}
         ///End Compute flow and forces
@@ -800,7 +833,7 @@
 			boost::thread workerThread(&PeriodicFlowEngine::backgroundAction,this);
 			workerThread.detach();
 			Initialize_volumes(solver);
-			if (viscousShear) ApplyViscousForces(*solver);
+			ComputeViscousForces(*solver);
 		}
 		else if (Debug && !first) {
 			if (Debug && !backgroundCompleted) cerr<<"still computing solver in the background"<<endl;
@@ -810,10 +843,9 @@
 			cachedCell= Cell(*(scene->cell));
 			Build_Triangulation (P_zero, solver);
 			Initialize_volumes(solver);
-			if (viscousShear) ApplyViscousForces(*solver);
+			ComputeViscousForces(*solver);
                		Update_Triangulation = false;}
         }
-// 	if (velocity_profile) /*flow->FluidVelocityProfile();*/solver->Average_Fluid_Velocity();
         first=false;
 	timingDeltas->checkpoint("Ending");
 }
@@ -832,8 +864,6 @@
 
 void PeriodicFlowEngine::Triangulate( shared_ptr<FlowSolver>& flow )
 {
-//         shared_ptr<Sphere> sph ( new Sphere );
-//         int Sph_Index = sph->getClassIndexStatic();
         Tesselation& Tes = flow->T[flow->currentTes];
 	vector<posData>& buffer = multithread ? positionBufferParallel : positionBufferCurrent;
 	FOREACH ( const posData& b, buffer ) {
@@ -848,7 +878,9 @@
                 const Real& z = wpos[2];
                 Vertex_handle vh0=Tes.insert ( x, y, z, rad, id );
 //                 Vertex_handle vh0=Tes.insert ( b.pos[0], b.pos[1], b.pos[2], b.radius, b.id );
-		if (vh0==NULL) {LOG_ERROR("Vh NULL in PeriodicFlowEngine::Triangulate(), check input data"); continue;}
+		if (vh0==NULL) {
+			flow->errorCode = 2;
+			LOG_ERROR("Vh NULL in PeriodicFlowEngine::Triangulate(), check input data"); continue;}
 		for ( int k=0;k<3;k++ ) vh0->info().period[k]=-period[k];
                 const Vector3r cellSize ( cachedCell.getSize() );
 		//FIXME: if hasShear, comment in
@@ -860,17 +892,18 @@
                 for ( i[0]=-1; i[0]<=1; i[0]++ )
                         for ( i[1]=-1;i[1]<=1; i[1]++ )
                                 for ( i[2]=-1; i[2]<=1; i[2]++ ) {
-                                        if ( i[0]==0 && i[1]==0 && i[2]==0 ) continue; // middle; already rendered above
+                                        if ( i[0]!=0 || i[1]!=0 || i[2]!=0 ) { // middle; already rendered above
                                         Vector3r pos2=wpos+Vector3r ( cellSize[0]*i[0],cellSize[1]*i[1],cellSize[2]*i[2] ); // shift, but without shear!
                                         pmin=pos2-halfSize;
                                         pmax=pos2+halfSize;
-                                        if ( pmin[0]<=cellSize[0] && pmax[0]>=0 && pmin[1]<=cellSize[1] && pmax[1]>=0 && pmin[2]<=cellSize[2] && pmax[2]>=0 ) {
+                                        if ( (pmin[0]<=cellSize[0]) && (pmax[0]>=0) && (pmin[1]<=cellSize[1]) && (pmax[1]>=0) && (pmin[2]<=cellSize[2]) && (pmax[2]>=0) ) {
                                                 //with shear:
                                                 //Vector3r pt=scene->cell->shearPt ( pos2 );
                                                 //without shear:
                                                 const Vector3r& pt= pos2;
                                                 Vertex_handle vh=Tes.insert ( pt[0],pt[1],pt[2],rad,id,false,id );
                                                 for ( int k=0;k<3;k++ ) vh->info().period[k]=i[k]-period[k];}}
+				}
 		//re-assign the original vertex pointer since duplicates may have overwrite it
 		Tes.vertexHandles[id]=vh0;
         }
@@ -922,7 +955,10 @@
 
 void PeriodicFlowEngine::locateCell ( Cell_handle baseCell, unsigned int& index, int& baseIndex, shared_ptr<FlowSolver>& flow, unsigned int count)
 {
-        if (count>10) LOG_ERROR("More than 10 attempts to locate a cell, duplicateThreshold may be too small, resulting in periodicity inconsistencies.");
+        if (count>10) {
+		LOG_ERROR("More than 10 attempts to locate a cell, duplicateThreshold may be too small, resulting in periodicity inconsistencies.");
+		flow->errorCode=1; return;
+	}
 	PeriFlowTesselation::Cell_Info& base_info = baseCell->info();
         //already located, return FIXME: is inline working correctly? else move this test outside the function, just before the calls
 	if ( base_info.index>0 || base_info.isGhost ) return;
@@ -950,7 +986,6 @@
 			base_info.isGhost=false;
 			return;
 		}
-// 		const Vertex_handle& v0 = flow->T[flow->currentTes].vertexHandles[baseCell->vertex(0)->info().id()];
 		Cell_handle ch= Tri.locate ( CGT::Point ( wdCenter[0],wdCenter[1],wdCenter[2] )
 // 					     ,/*hint*/ v0
 					     );
@@ -1076,7 +1111,9 @@
 	Tes.cellHandles.resize(Tes.Triangulation().number_of_finite_cells());
 	const Finite_cells_iterator cellend=Tes.Triangulation().finite_cells_end();
         for ( Finite_cells_iterator cell=Tes.Triangulation().finite_cells_begin(); cell!=cellend; cell++ ){
+// 		if (cell->vertex(0)->info().isGhost && cell->vertex(1)->info().isGhost && cell->vertex(2)->info().isGhost && cell->vertex(3)->info().isGhost) { cell->info().isGhost=true; continue;} //crash, why?
                 locateCell ( cell,index,baseIndex,flow );
+		if (flow->errorCode>0) return;
 		//Fill this vector than can be later used to speedup loops
 		if (!cell->info().isGhost) Tes.cellHandles[cell->info().baseIndex]=cell;
 	}
@@ -1093,8 +1130,7 @@
 // 	if ( !first && (useSolver==0 || fluidBulkModulus>0)) flow->Interpolate ( flow->T[!flow->currentTes], flow->T[flow->currentTes] );
 	
         if ( WaveAction ) flow->ApplySinusoidalPressure ( Tes.Triangulation(), Sinus_Amplitude, Sinus_Average, 30 );
-        if ( viscousShear ) flow->ComputeEdgesSurfaces();
-	if ( normalLubrication ) flow->ComputeEdgesSurfaces();
+        if ( viscousShear || normalLubrication || shearLubrication) flow->computeEdgesSurfaces();
 	if ( Debug ) cout << endl << "end buildTri------" << endl << endl;
 }
 

=== modified file 'pkg/dem/FlowEngine.hpp'
--- pkg/dem/FlowEngine.hpp	2012-11-27 18:31:45 +0000
+++ pkg/dem/FlowEngine.hpp	2013-05-15 16:37:49 +0000
@@ -1,6 +1,7 @@
 /*************************************************************************
-*  Copyright (C) 2009 by Emanuele Catalano                               *
-*  emanuele.catalano@xxxxxxxxxxx                                            *
+*  Copyright (C) 2009 by Emanuele Catalano <catalano@xxxxxxxxxxxxxxx>    *
+*  Copyright (C) 2009 by Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>     *
+*  Copyright (C) 2012 by Donia Marzougui <donia.marzougui@xxxxxxxxxxxxxxx>*
 *                                                                        *
 *  This program is free software; it is licensed under the terms of the  *
 *  GNU General Public License v2 or later. See file LICENSE for details. *
@@ -34,6 +35,7 @@
 	typedef FlowSolver::Cell_handle						Cell_handle;
 	typedef FlowSolver::Vertex_handle					Vertex_handle;
 	typedef RTriangulation::Finite_edges_iterator				Finite_edges_iterator;
+	typedef FlowSolver::Vertex_handle                    			Vertex_handle;
 
 
 	
@@ -75,7 +77,7 @@
 		TPL void setImposedPressure(unsigned int cond, Real p,Solver& flow);
 		TPL void clearImposedPressure(Solver& flow);
 		TPL void clearImposedFlux(Solver& flow);
-		TPL void ApplyViscousForces(Solver& flow);
+		TPL void ComputeViscousForces(Solver& flow);
 		TPL Real getCellFlux(unsigned int cond, const shared_ptr<Solver>& flow);
 		TPL Real getBoundaryFlux(unsigned int boundary,Solver& flow) {return flow->boundaryFlux(boundary);}
 		TPL Vector3r fluidForce(unsigned int id_sph, Solver& flow) {
@@ -90,6 +92,21 @@
 			return (flow->viscousBodyStress.size()>id_sph)?flow->viscousBodyStress[id_sph]:Matrix3r::Zero();}
 		TPL Matrix3r bodyNormalLubStress(unsigned int id_sph, Solver& flow) {
 			return (flow->lubBodyStress.size()>id_sph)?flow->lubBodyStress[id_sph]:Matrix3r::Zero();}
+		TPL python::list getConstrictions(bool all, Solver& flow) {
+			vector<Real> csd=flow->getConstrictions(); python::list pycsd;
+			for (unsigned int k=0;k<csd.size();k++) if ((all && csd[k]!=0) || csd[k]>0) pycsd.append(csd[k]); return pycsd;}
+		TPL python::list getConstrictionsFull(bool all, Solver& flow) {
+			vector<Constriction> csd=flow->getConstrictionsFull(); python::list pycsd;
+			for (unsigned int k=0;k<csd.size();k++) if ((all && csd[k].second[0]!=0) || csd[k].second[0]>0) {
+				python::list cons;
+				cons.append(csd[k].first.first);
+				cons.append(csd[k].first.second);
+				cons.append(csd[k].second[0]);
+				cons.append(csd[k].second[1]);
+				cons.append(csd[k].second[2]);
+				cons.append(csd[k].second[3]);
+				pycsd.append(cons);}
+			return pycsd;}
 		
 		template<class Cellhandle>
 		Real Volume_cell_single_fictious (Cellhandle cell);
@@ -103,21 +120,21 @@
 		void Average_real_cell_velocity();
 		void saveVtk() {solver->saveVtk();}
 		vector<Real> AvFlVelOnSph(unsigned int id_sph) {return solver->Average_Fluid_Velocity_On_Sphere(id_sph);}
-		python::list getConstrictions() {
-			vector<Real> csd=solver->getConstrictions(); python::list pycsd;
-			for (unsigned int k=0;k<csd.size();k++) pycsd.append(csd[k]); return pycsd;}
+
 		void setBoundaryVel(Vector3r vel) {topBoundaryVelocity=vel; Update_Triangulation=true;}
 		void PressureProfile(double wallUpY, double wallDownY) {return solver->MeasurePressureProfile(wallUpY,wallDownY);}
 		double MeasurePorePressure(Vector3r pos){return solver->MeasurePorePressure(pos[0], pos[1], pos[2]);}
 		TPL int getCell(double posX, double posY, double posZ, Solver& flow){return flow->getCell(posX, posY, posZ);}
 		double MeasureAveragedPressure(double posY){return solver->MeasureAveragedPressure(posY);}
 		double MeasureTotalAveragedPressure(){return solver->MeasureTotalAveragedPressure();}
-		#ifdef EIGENSPARSE_LIB
+
+		#ifdef LINSOLV
 		TPL void exportMatrix(string filename,Solver& flow) {if (useSolver==3) flow->exportMatrix(filename.c_str());
 			else cerr<<"available for Cholmod solver (useSolver==3)"<<endl;}
 		TPL void exportTriplets(string filename,Solver& flow) {if (useSolver==3) flow->exportTriplets(filename.c_str());
 			else cerr<<"available for Cholmod solver (useSolver==3)"<<endl;}
 		#endif
+
 		void emulateAction(){
 			scene = Omega::instance().getScene().get();
 			action();}
@@ -137,10 +154,14 @@
 		Real 		_getCellFlux(unsigned int cond) {return getCellFlux(cond,solver);}
 		Real 		_getBoundaryFlux(unsigned int boundary) {return getBoundaryFlux(boundary,solver);}
 		int		_getCell(Vector3r pos) {return getCell(pos[0],pos[1],pos[2],solver);}
-		#ifdef EIGENSPARSE_LIB
+
+		#ifdef LINSOLV
 		void 		_exportMatrix(string filename) {exportMatrix(filename,solver);}
 		void 		_exportTriplets(string filename) {exportTriplets(filename,solver);}
 		#endif
+		python::list 	_getConstrictions(bool all) {return getConstrictions(all,solver);}
+		python::list 	_getConstrictionsFull(bool all) {return getConstrictionsFull(all,solver);}
+
 		virtual ~FlowEngine();
 
 		virtual void action();
@@ -179,6 +200,7 @@
 					((Real,maxKdivKmean,100,,"define the max K value (see :yref:`FlowEngine::clampKValues`)"))
 					((double,permeability_factor,0.0,,"permability multiplier"))
 					((double,viscosity,1.0,,"viscosity of fluid"))
+					((double,stiffness, 10000,,"stiffness modulus"))
 					((Real,loadFactor,1.1,,"Load multiplicator for oedometer test"))
 					((double, K, 0,, "Permeability of the sample"))
 					((int, useSolver, 0,, "Solver to use 0=G-Seidel, 1=Taucs, 2-Pardiso, 3-CHOLMOD"))
@@ -214,8 +236,11 @@
 					((bool, viscousShear, false,,"Compute viscous shear terms as developped by Donia Marzougui"))
 					((bool, shearLubrication, false,,"Compute shear lubrication force as developped by Brule"))
 					((double, eps, 0.00001,,"minimum distance between particles"))
+					((bool, pressureForce, true,,"Compute the pressure field and associated fluid forces. WARNING: turning off means fluid flow is not computed at all."))
 
 					((bool, normalLubrication, false,,"Compute normal lubrication force as developped by Brule"))
+					((bool, viscousNormalBodyStress, false,,"Compute normal viscous stress applied on each body"))
+					((bool, viscousShearBodyStress, false,,"Compute shear viscous stress applied on each body"))
 					((bool, multithread, false,,"Build triangulation and factorize in the background (multi-thread mode)"))
 					#ifdef EIGENSPARSE_LIB
 					((int, numSolveThreads, 1,,"number of openblas threads in the solve phase."))
@@ -246,7 +271,8 @@
 					.def("clearImposedFlux",&FlowEngine::_clearImposedFlux,"Clear the list of points with flux imposed.")
 					.def("getCellFlux",&FlowEngine::_getCellFlux,(python::arg("cond")),"Get influx in cell associated to an imposed P (indexed using 'cond').")
 					.def("getBoundaryFlux",&FlowEngine::_getBoundaryFlux,(python::arg("boundary")),"Get total flux through boundary defined by its body id.")
-					.def("getConstrictions",&FlowEngine::getConstrictions,"Get the list of constrictions (inscribed circle) for all finite facets.")
+					.def("getConstrictions",&FlowEngine::_getConstrictions,(python::arg("all")=true),"Get the list of constriction radii (inscribed circle) for all finite facets (if all==True) or all facets not incident to a virtual bounding sphere (if all==False).  When all facets are returned, negative radii denote facet incident to one or more fictious spheres.")
+					.def("getConstrictionsFull",&FlowEngine::_getConstrictionsFull,(python::arg("all")=true),"Get the list of constrictions (inscribed circle) for all finite facets (if all==True), or all facets not incident to a fictious bounding sphere (if all==False). When all facets are returned, negative radii denote facet incident to one or more fictious spheres. The constrictions are returned in the format {{cell1,cell2}{rad,nx,ny,nz}}")
 					.def("saveVtk",&FlowEngine::saveVtk,"Save pressure field in vtk format.")
 					.def("AvFlVelOnSph",&FlowEngine::AvFlVelOnSph,(python::arg("Id_sph")),"Compute a sphere-centered average fluid velocity")
 					.def("fluidForce",&FlowEngine::_fluidForce,(python::arg("Id_sph")),"Return the fluid force on sphere Id_sph.")
@@ -264,7 +290,8 @@
 					.def("updateBCs",&FlowEngine::_updateBCs,"tells the engine to update it's boundary conditions before running (especially useful when changing boundary pressure - should not be needed for point-wise imposed pressure)")
 					.def("emulateAction",&FlowEngine::emulateAction,"get scene and run action (may be used to manipulate engine outside the main loop).")
 					.def("getCell",&FlowEngine::_getCell,(python::arg("pos")),"get id of the cell containing (X,Y,Z).")
-					#ifdef EIGENSPARSE_LIB
+
+					#ifdef LINSOLV
 					.def("exportMatrix",&FlowEngine::_exportMatrix,(python::arg("filename")="matrix"),"Export system matrix to a file with all entries (even zeros will displayed).")
 					.def("exportTriplets",&FlowEngine::_exportTriplets,(python::arg("filename")="triplets"),"Export system matrix to a file with only non-zero entries.")
 					#endif
@@ -320,19 +347,6 @@
 		inline void locateCell(Cell_handle baseCell, unsigned int& index, int& baseIndex, shared_ptr<FlowSolver>& flow, unsigned int count=0);
 		Vector3r meanVelocity();
 
-		python::list getConstrictionsFull() {
-			vector<Constriction> csd=solver->getConstrictionsFull(); python::list pycsd;
-			for (unsigned int k=0;k<csd.size();k++) {
-				python::list cons;
-				cons.append(csd[k].first.first);
-				cons.append(csd[k].first.second);
-				cons.append(csd[k].second[0]);
-				cons.append(csd[k].second[1]);
-				cons.append(csd[k].second[2]);
-				cons.append(csd[k].second[3]);
-				pycsd.append(cons);}
-			return pycsd;}
-		
 		virtual ~PeriodicFlowEngine();
 
 		virtual void action();
@@ -359,7 +373,8 @@
 		void 		PressureProfile(double wallUpY, double wallDownY) {return solver->MeasurePressureProfile(wallUpY,wallDownY);}
 
 		int		_getCell(Vector3r pos) {return getCell(pos[0],pos[1],pos[2],solver);}
-		#ifdef EIGENSPARSE_LIB
+
+		#ifdef LINSOLV
 		void 		_exportMatrix(string filename) {exportMatrix(filename,solver);}
 		void 		_exportTriplets(string filename) {exportTriplets(filename,solver);}
 		#endif
@@ -367,6 +382,18 @@
 // 		void 		_setImposedPressure(unsigned int cond, Real p) {setImposedPressure(cond,p,solver);}
 // 		void 		_clearImposedPressure() {clearImposedPressure(solver);}
 		Real 		_getCellFlux(unsigned int cond) {return getCellFlux(cond,solver);}
+		python::list 	_getConstrictions(bool all) {return getConstrictions(all,solver);}
+		python::list 	_getConstrictionsFull(bool all) {return getConstrictionsFull(all,solver);}
+
+		//commodities
+		void compTessVolumes() {
+			solver->T[solver->currentTes].Compute();
+			solver->T[solver->currentTes].ComputeVolumes();
+		}
+		Real getVolume (Body::id_t id) {
+			if (solver->T[solver->currentTes].Max_id() <= 0) {emulateAction(); LOG_WARN("Not triangulated yet, emulating action");}
+			if (solver->T[solver->currentTes].Volume(id) == -1) {compTessVolumes(); LOG_WARN("Computing all volumes now, as you did not request it explicitely.");}
+			return (solver->T[solver->currentTes].Max_id() >= id) ? solver->T[solver->currentTes].Volume(id) : -1;}
 
 		YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(PeriodicFlowEngine,FlowEngine,"An engine to solve flow problem in saturated granular media",
 			((Real,duplicateThreshold, 0.06,,"distance from cell borders that will triger periodic duplication in the triangulation |yupdate|"))
@@ -398,11 +425,14 @@
 			.def("updateBCs",&PeriodicFlowEngine::_updateBCs,"tells the engine to update it's boundary conditions before running (especially useful when changing boundary pressure - should not be needed for point-wise imposed pressure)")
 			
 			.def("getCell",&PeriodicFlowEngine::_getCell,python::arg("pos"),"get id of the cell containing 'pos'.")
-			.def("getConstrictionsFull",&PeriodicFlowEngine::getConstrictionsFull,"Get the list of constrictions (inscribed circle) for all finite facets.")
-			#ifdef EIGENSPARSE_LIB
+			.def("getConstrictions",&PeriodicFlowEngine::_getConstrictions,(python::arg("all")=true),"Get the list of constriction radii (inscribed circle) for all finite facets (if all==True) or all facets not incident to a virtual bounding sphere (if all==False).  When all facets are returned, negative radii denote facet incident to one or more fictious spheres.")
+			.def("getConstrictionsFull",&PeriodicFlowEngine::_getConstrictionsFull,(python::arg("all")=true),"Get the list of constrictions (inscribed circle) for all finite facets (if all==True), or all facets not incident to a fictious bounding sphere (if all==False). When all facets are returned, negative radii denote facet incident to one or more fictious spheres. The constrictions are returned in the format {{cell1,cell2}{rad,nx,ny,nz}}")
+			#ifdef LINSOLV
 			.def("exportMatrix",&PeriodicFlowEngine::_exportMatrix,(python::arg("filename")="matrix"),"Export system matrix to a file with all entries (even zeros will displayed).")
 			.def("exportTriplets",&PeriodicFlowEngine::_exportTriplets,(python::arg("filename")="triplets"),"Export system matrix to a file with only non-zero entries.")
 			#endif
+			.def("compTessVolumes",&PeriodicFlowEngine::compTessVolumes,"Like TesselationWrapper::computeVolumes()")
+			.def("volume",&PeriodicFlowEngine::getVolume,(python::arg("id")=0),"Returns the volume of Voronoi's cell of a sphere.")
 		)
 		DECLARE_LOGGER;
 

=== modified file 'pkg/dem/GlobalStiffnessTimeStepper.cpp'
--- pkg/dem/GlobalStiffnessTimeStepper.cpp	2012-08-24 11:19:25 +0000
+++ pkg/dem/GlobalStiffnessTimeStepper.cpp	2013-02-04 18:23:35 +0000
@@ -57,12 +57,9 @@
 	
 	Real Rdt =  std::min( std::min (dtx, dty), dtz );//Rdt = smallest squared eigenperiod for rotational motions
 	dt = 1.41044*timestepSafetyCoefficient*std::sqrt(std::min(dt,Rdt));//1.41044 = sqrt(2)
-	//if there is a target dt, then we apply density scaling on the body
+	//if there is a target dt, then we apply density scaling on the body, the inertia used in Newton will be mass*scaling, the weight is unmodified
 	if (densityScaling) {
-// 		Real prevSc = sdec->densityScaling;
-		sdec->densityScaling = min(1.001*sdec->densityScaling,timestepSafetyCoefficient*pow(dt /targetDt,2.0));
-// 		sdec->vel*=min(pow(sdec->densityScaling/prevSc,2),1.);
-// 		sdec->angVel*=min(pow(sdec->densityScaling/prevSc,2),1.);
+		sdec->densityScaling = min(sdec->densityScaling,timestepSafetyCoefficient*pow(dt /targetDt,2.0));
 		newDt=targetDt;
 	}
 	//else we update dt normaly

=== modified file 'pkg/dem/GlobalStiffnessTimeStepper.hpp'
--- pkg/dem/GlobalStiffnessTimeStepper.hpp	2012-08-24 11:19:25 +0000
+++ pkg/dem/GlobalStiffnessTimeStepper.hpp	2013-04-09 14:14:48 +0000
@@ -37,12 +37,12 @@
 		virtual void computeTimeStep(Scene*);
 		virtual bool isActivated();
 		YADE_CLASS_BASE_DOC_ATTRS_CTOR(
-			GlobalStiffnessTimeStepper,TimeStepper,"An engine assigning the time-step as a fraction of the minimum eigen-period in the problem",
+			GlobalStiffnessTimeStepper,TimeStepper,"An engine assigning the time-step as a fraction of the minimum eigen-period in the problem. The derivation is detailed in the chapter on `DEM formulation <https://www.yade-dem.org/doc/formulation.html#dem-simulations>`_",
 			((Real,defaultDt,-1,,"used as the initial value of the timestep (especially useful in the first steps when no contact exist). If negative, it will be defined by :yref:`utils.PWaveTimeStep` * :yref:`GlobalStiffnessTimeStepper::timestepSafetyCoefficient`"))
 			((Real,maxDt,Mathr::MAX_REAL,,"if positive, used as max value of the timestep whatever the computed value"))
 			((Real,previousDt,1,,"last computed dt |yupdate|"))
 			((Real,timestepSafetyCoefficient,0.8,,"safety factor between the minimum eigen-period and the final assigned dt (less than 1))"))
-			((bool,densityScaling,false,,"|yupdate| don't modify this value. see :yref:`NewtonIntegrator::densityScaling` and :yref:`NewtonIntegrator::densityScaling`"))
+			((bool,densityScaling,false,,"|yupdate| don't modify this value if you don't plan to modify the scaling factor manually for some bodies. In most cases, it is enough to set :yref:`NewtonIntegrator::densityScaling` and let this one be adjusted automatically."))
 			((Real,targetDt,1,,"if :yref:`NewtonIntegrator::densityScaling` is active, this value will be used as the simulation  timestep and the scaling will use this value of dt as the target value. The value of targetDt is arbitrary and should have no effect in the result in general. However if some bodies have imposed velocities, for instance, they will move more or less per each step depending on this value.")),
 			computedOnce=false;)
 		DECLARE_LOGGER;

=== modified file 'pkg/dem/Ig2_Facet_Sphere_ScGeom.cpp'
--- pkg/dem/Ig2_Facet_Sphere_ScGeom.cpp	2011-02-14 08:05:09 +0000
+++ pkg/dem/Ig2_Facet_Sphere_ScGeom.cpp	2013-04-25 11:35:51 +0000
@@ -13,8 +13,9 @@
 #include<yade/pkg/common/Wall.hpp>
 #include<yade/core/Scene.hpp>
 #include<yade/lib/base/Math.hpp>
+#include<yade/pkg/common/InteractionLoop.hpp>
 
-YADE_PLUGIN((Ig2_Facet_Sphere_ScGeom)(Ig2_Wall_Sphere_ScGeom));
+YADE_PLUGIN((Ig2_Facet_Sphere_ScGeom)(Ig2_Facet_Sphere_ScGeom6D)(Ig2_Wall_Sphere_ScGeom));
 
 CREATE_LOGGER(Ig2_Facet_Sphere_ScGeom);
 
@@ -26,6 +27,7 @@
 							const bool& force,
 							const shared_ptr<Interaction>& c)
 {
+	TIMING_DELTAS_START();
 	const Se3r& se31=state1.se3; const Se3r& se32=state2.se3;
 	Facet*   facet = static_cast<Facet*>(cm1.get());
 	/* could be written as (needs to be tested):
@@ -45,7 +47,10 @@
 	if (L<0) {normal=-normal; L=-L; }
 
 	Real sphereRadius = static_cast<Sphere*>(cm2.get())->radius;
-	if (L>sphereRadius && !c->isReal() && !force)  return false; // no contact, but only if there was no previous contact; ortherwise, the constitutive law is responsible for setting Interaction::isReal=false
+	if (L>sphereRadius && !c->isReal() && !force) { // no contact, but only if there was no previous contact; ortherwise, the constitutive law is responsible for setting Interaction::isReal=false
+		TIMING_DELTAS_CHECKPOINT("Ig2_Facet_Sphere_ScGeom");
+		return false;
+	}
 
 	Vector3r cp = cl - L*normal;
 	const Vector3r* ne = facet->ne;
@@ -111,8 +116,10 @@
 		scm->radius2 = sphereRadius;
 		if (isNew) c->geom = scm;
 		scm->precompute(state1,state2,scene,c,normal,isNew,shift2,false/*avoidGranularRatcheting only for sphere-sphere*/);
+		TIMING_DELTAS_CHECKPOINT("Ig2_Facet_Sphere_ScGeom");
 		return true;
 	}
+	TIMING_DELTAS_CHECKPOINT("Ig2_Facet_Sphere_ScGeom");
 	return false;
 }
 
@@ -130,6 +137,41 @@
 	return go(cm2,cm1,state2,state1,-shift2,force,c);
 }
 
+bool Ig2_Facet_Sphere_ScGeom6D::go(const shared_ptr<Shape>& cm1,
+							const shared_ptr<Shape>& cm2,
+							const State& state1,
+							const State& state2,
+							const Vector3r& shift2,
+							const bool& force,
+							const shared_ptr<Interaction>& c)
+{
+	bool isNew = !c->geom;
+	if (Ig2_Facet_Sphere_ScGeom::go(cm1,cm2,state1,state2,shift2,force,c)) {
+		if (isNew) {//generate a 6DOF interaction from the 3DOF one generated by Ig2_Facet_Sphere_ScGeom
+			shared_ptr<ScGeom6D> sc(new ScGeom6D());
+			*(YADE_PTR_CAST<ScGeom>(sc)) = *(YADE_PTR_CAST<ScGeom>(c->geom));
+			c->geom=sc;
+		}
+		YADE_PTR_CAST<ScGeom6D>(c->geom)->precomputeRotations(state1,state2,isNew,false);
+		return true;
+	}
+	else return false;
+}
+
+
+bool Ig2_Facet_Sphere_ScGeom6D::goReverse(	const shared_ptr<Shape>& cm1,
+								const shared_ptr<Shape>& cm2,
+								const State& state1,
+								const State& state2,
+								const Vector3r& shift2,
+								const bool& force,
+								const shared_ptr<Interaction>& c)
+{
+	c->swapOrder();
+	return go(cm2,cm1,state2,state1,-shift2,force,c);
+}
+
+
 
 /********* Wall + Sphere **********/
 

=== modified file 'pkg/dem/Ig2_Facet_Sphere_ScGeom.hpp'
--- pkg/dem/Ig2_Facet_Sphere_ScGeom.hpp	2011-01-09 16:34:50 +0000
+++ pkg/dem/Ig2_Facet_Sphere_ScGeom.hpp	2013-04-25 11:35:51 +0000
@@ -41,6 +41,28 @@
 
 REGISTER_SERIALIZABLE(Ig2_Facet_Sphere_ScGeom);
 
+class Ig2_Facet_Sphere_ScGeom6D : public Ig2_Facet_Sphere_ScGeom
+{
+	public :
+		virtual bool go(const shared_ptr<Shape>& cm1,
+					const shared_ptr<Shape>& cm2,
+					const State& state1,
+					const State& state2,
+					const Vector3r& shift2,
+					const bool& force,
+					const shared_ptr<Interaction>& c);
+		virtual bool goReverse(	const shared_ptr<Shape>& cm1,
+					const shared_ptr<Shape>& cm2,
+					const State& state1,
+					const State& state2,
+					const Vector3r& shift2,
+					const bool& force,
+					const shared_ptr<Interaction>& c);
+	YADE_CLASS_BASE_DOC(Ig2_Facet_Sphere_ScGeom6D,Ig2_Facet_Sphere_ScGeom,"Create an interaction geometry :yref:`ScGeom6D` from :yref:`Facet` and :yref:`Sphere`, representing the Facet with a projected virtual sphere of same radius.")
+	FUNCTOR2D(Facet,Sphere);
+	DEFINE_FUNCTOR_ORDER_2D(Facet,Sphere);
+};
+REGISTER_SERIALIZABLE(Ig2_Facet_Sphere_ScGeom6D);
 
 class Ig2_Wall_Sphere_ScGeom: public IGeomFunctor{
 	public:

=== modified file 'pkg/dem/Ig2_Sphere_Sphere_ScGeom.cpp'
--- pkg/dem/Ig2_Sphere_Sphere_ScGeom.cpp	2010-12-31 14:35:21 +0000
+++ pkg/dem/Ig2_Sphere_Sphere_ScGeom.cpp	2013-04-23 14:07:34 +0000
@@ -8,15 +8,21 @@
 #include<yade/core/Scene.hpp>
 #include<yade/lib/base/Math.hpp>
 #include<yade/core/Omega.hpp>
+#include<yade/pkg/common/InteractionLoop.hpp>
 
 bool Ig2_Sphere_Sphere_ScGeom::go(	const shared_ptr<Shape>& cm1, const shared_ptr<Shape>& cm2, const State& state1, const State& state2, const Vector3r& shift2, const bool& force, const shared_ptr<Interaction>& c)
 {
+	TIMING_DELTAS_START();
 	const Se3r& se31=state1.se3; const Se3r& se32=state2.se3;
 	const Sphere *s1=static_cast<Sphere*>(cm1.get()), *s2=static_cast<Sphere*>(cm2.get());
 	Vector3r normal=(se32.position+shift2)-se31.position;
 	if (!c->isReal() && !force) {//don't fast-check distance if geometry will be updated anyway
 		Real penetrationDepthSq=pow(interactionDetectionFactor*(s1->radius+s2->radius),2) - normal.squaredNorm();
-		if (penetrationDepthSq<0) return false;}
+		if (penetrationDepthSq<0) {
+			TIMING_DELTAS_CHECKPOINT("Ig2_Sphere_Sphere_ScGeom");
+			return false;
+		}
+	}
 	shared_ptr<ScGeom> scm;
 	bool isNew = !c->geom;
 	if(!isNew) scm=YADE_PTR_CAST<ScGeom>(c->geom);
@@ -31,6 +37,7 @@
 	scm->radius1=s1->radius;
 	scm->radius2=s2->radius;
 	scm->precompute(state1,state2,scene,c,normal,isNew,shift2,avoidGranularRatcheting);
+	TIMING_DELTAS_CHECKPOINT("Ig2_Sphere_Sphere_ScGeom");
 	return true;
 }
 

=== added file 'pkg/dem/InelastCohFrictMat.cpp'
--- pkg/dem/InelastCohFrictMat.cpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/InelastCohFrictMat.cpp	2012-12-14 14:38:44 +0000
@@ -0,0 +1,7 @@
+#include "InelastCohFrictMat.hpp"
+
+InelastCohFrictMat::~InelastCohFrictMat()
+{
+}
+
+YADE_PLUGIN((InelastCohFrictMat));
\ No newline at end of file

=== added file 'pkg/dem/InelastCohFrictMat.hpp'
--- pkg/dem/InelastCohFrictMat.hpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/InelastCohFrictMat.hpp	2012-12-14 14:38:44 +0000
@@ -0,0 +1,37 @@
+#pragma once
+
+#include "CohFrictMat.hpp"
+
+
+class InelastCohFrictMat : public CohFrictMat
+{
+	public :
+		virtual ~InelastCohFrictMat ();
+
+/// Serialization
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR(InelastCohFrictMat,CohFrictMat,"",
+		((Real,eTT,0.0,,"Tension elasticity modulus"))
+		((Real,eTC,0.0,,"Compresion elasticity modulus"))
+		((Real,eB,0.0,,"bending elasticity modulus"))
+		((Real,gTw,0.0,,"twist elasticity modulus"))	
+		((Real,sigmaB,0.0,,"max. Bending stress"))
+		((Real,sigmaTw,0.0,,"max. Twist stress"))
+		((Real,creepT,0.0,,"Tension/compression creeping"))
+		((Real,creepB,0.0,,"bending creeping"))
+		((Real,creepTw,0.0,,"twist creeping"))
+		((Real,unloadT,0.0,,"Tension/compression plastic unload"))
+		((Real,unloadB,0.0,,"bending plastic unload"))
+		((Real,unloadTw,0.0,,"twist plastic unload"))
+		((Real,disElT,0.0,,"max elastic displacement on Traction"))
+		((Real,disElC,0.0,,"max elastic displacement on Compresion"))
+		((Real,epsilonMaxT,0.0,,"Maximal plastic strain Tension"))
+		((Real,epsilonMaxC,0.0,,"Maximal plastic strain compression"))
+		((Real,phiBMax,0.0,,"Maximal plastic bending strain"))
+		((Real,phiTwMax,0.0,,"Maximal plastic bending strain")),
+		createIndex();			  
+					);
+/// Indexable
+	REGISTER_CLASS_INDEX(InelastCohFrictMat,CohFrictMat);
+};
+
+REGISTER_SERIALIZABLE(InelastCohFrictMat);

=== added file 'pkg/dem/InelastCohFrictPhys.cpp'
--- pkg/dem/InelastCohFrictPhys.cpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/InelastCohFrictPhys.cpp	2012-12-14 14:38:44 +0000
@@ -0,0 +1,14 @@
+#include "InelastCohFrictPhys.hpp"
+
+
+void InelastCohFrictPhys::SetBreakingState()
+{	
+	cohesionBroken = true;
+	normalAdhesion = 0;
+	shearAdhesion = 0;
+}
+
+InelastCohFrictPhys::~InelastCohFrictPhys()
+{
+}
+YADE_PLUGIN((InelastCohFrictPhys));
\ No newline at end of file

=== added file 'pkg/dem/InelastCohFrictPhys.hpp'
--- pkg/dem/InelastCohFrictPhys.hpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/InelastCohFrictPhys.hpp	2013-05-14 21:24:11 +0000
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "CohFrictPhys.hpp"
+
+
+class InelastCohFrictPhys : public CohFrictPhys
+{
+	public :
+		virtual ~InelastCohFrictPhys();
+		void SetBreakingState ();
+
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR(InelastCohFrictPhys,CohFrictPhys,"",
+		((bool,cohesionBroken,false,,"is cohesion active? will be set false when a fragile contact is broken"))
+		((bool,fragile,false,,"do cohesion disapear when contact strength is exceeded?"))
+		((Real,knT,0,,"tension stiffness [N.m/rad]"))
+		((Real,knC,0,,"compression stiffness [N.m/rad]"))
+		((Real,kt,0,,"twist shear stiffness [N.m/rad]"))
+		((Real,ks,0,,"shear stiffness [N.m/rad]"))
+		((Real,kr,0,,"bending stiffness [N.m/rad]"))
+		((Real,maxElastB,0.0,,"max. elastic Bending, zero if non elasto-plastic behavour "))
+		((Real,maxElastTw,0.0,,"max. elastic Twist, zero if non elasto-plastic behavour "))
+		((Real,dElT,0.0,,"Max elastic displacement Tension"))
+		((Real,dElC,0.0,,"Max elastic displacement Compression"))
+		((Real,crpT,0.0,,"Bending creep"))
+		((Real,crpB,0.0,,"Tension crepp"))
+		((Real,crpTw,0.0,,"Twist creep "))
+		((Real,epsMaxT,0.0,,"Maximal plastic strain Tension"))
+		((Real,epsMaxC,0.0,,"Maximal plastic strain compression"))
+		((Real,phBMax,0.0,,"Maximal plastic bending strain"))
+		((Real,phTwMax,0.0,,"Maximal plastic bending strain"))
+		((Real,unldT,0.0,,"Tension/compression plastic unload"))
+		((Real,unldB,0.0,,"bending plastic unload"))
+		((Real,unldTw,0.0,,"twist plastic unload"))
+		((bool,isBrokenB,false,,"true if bend plastic fracture achieved"))
+		((bool,isBrokenT,false,,"true if Traction or compression plastic fracture achieved"))
+		((bool,isBrokenTw,false,,"true if twist plastic fracture achieved"))
+		((bool,unloadedT,false,,"true if unload in Traction plastic deformation"))
+		((bool,unloadedC,false,,"true if unload in compression plastic deformation"))
+		((bool,unloadedB,false,,"true if unload in bending plastic deformation"))
+		((bool,unloadedTw,false,,"true if unload in twist plastic deformation"))
+		((Real,normalAdhesion,0,,"tensile strength"))
+		((Real,shearAdhesion,0,,"cohesive part of the shear strength (a frictional term might be added depending on :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment::always_use_moment_law`)"))
+		((Real,unp,0,,"plastic normal displacement, only used for tensile behaviour and if :yref:`CohFrictPhys::fragile`=false."))
+		((bool,onPlastic,false,,"true if plastic behaviour achieved, for creeping calculation"))
+		// internal attributes
+		,
+		createIndex();
+	);
+/// Indexable
+	REGISTER_CLASS_INDEX(InelastCohFrictPhys,CohFrictPhys);
+
+};
+
+REGISTER_SERIALIZABLE(InelastCohFrictPhys);

=== added file 'pkg/dem/Ip2_2xInelastCohFrictMat_InelastCohFrictPhys.cpp'
--- pkg/dem/Ip2_2xInelastCohFrictMat_InelastCohFrictPhys.cpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/Ip2_2xInelastCohFrictMat_InelastCohFrictPhys.cpp	2012-12-14 14:38:44 +0000
@@ -0,0 +1,110 @@
+#include "Ip2_2xInelastCohFrictMat_InelastCohFrictPhys.hpp"
+
+
+
+
+void Ip2_2xInelastCohFrictMat_InelastCohFrictPhys::go(const shared_ptr<Material>& b1    // InelastCohFrictMat
+                                        , const shared_ptr<Material>& b2 // InelastCohFrictMat
+                                        , const shared_ptr<Interaction>& interaction)
+{
+	
+	InelastCohFrictMat* sdec1 = static_cast<InelastCohFrictMat*>(b1.get());
+	InelastCohFrictMat* sdec2 = static_cast<InelastCohFrictMat*>(b2.get());
+	ScGeom6D* geom = YADE_CAST<ScGeom6D*>(interaction->geom.get());
+
+	//Create cohesive interractions only once
+	if (setCohesionNow && cohesionDefinitionIteration==-1) cohesionDefinitionIteration=scene->iter;
+	if (setCohesionNow && cohesionDefinitionIteration!=-1 && cohesionDefinitionIteration!=scene->iter) {
+		cohesionDefinitionIteration = -1;
+		setCohesionNow = 0;}
+
+	if (geom) {
+		if (!interaction->phys) {
+			interaction->phys = shared_ptr<InelastCohFrictPhys>(new InelastCohFrictPhys());
+			InelastCohFrictPhys* contactPhysics = YADE_CAST<InelastCohFrictPhys*>(interaction->phys.get());
+// 			Real Ea 	= sdec1->young;
+// 			Real Eb 	= sdec2->young;
+// 			Real Va 	= sdec1->poisson;
+// 			Real Vb 	= sdec2->poisson;
+			Real Da 	= geom->radius1;
+			Real Db 	= geom->radius2;
+			Real fa 	= sdec1->frictionAngle;
+			Real fb 	= sdec2->frictionAngle;
+			//Real Kn = 2.0*Ea*Da*Eb*Db/(Ea*Da+Eb*Db);//harmonic average of two stiffnesses
+
+			// harmonic average of modulus
+			Real ETC = 2.0*sdec1->eTC*sdec2->eTC/(sdec1->eTC+sdec2->eTC);
+			Real ETT = 2.0*sdec1->eTT*sdec2->eTT/(sdec1->eTT+sdec2->eTT);
+
+			Real EB = 2.0*sdec1->eB*sdec2->eB/(sdec1->eB+sdec2->eB);
+			Real GTw = 2.0*sdec1->gTw*sdec2->gTw/(sdec1->gTw+sdec2->gTw);
+
+			contactPhysics->crpT = std::min(sdec1->creepT,sdec2->creepT);
+			contactPhysics->crpB = std::min(sdec1->creepB,sdec2->creepB);
+			contactPhysics->crpTw = std::min(sdec1->creepTw,sdec2->creepTw);
+			//
+			
+// 			Real Ks;
+// 			if (Va && Vb) Ks = 2.0*Ea*Da*Va*Eb*Db*Vb/(Ea*Da*Va+Eb*Db*Vb);//harmonic average of two stiffnesses with ks=V*kn for each sphere
+// 			else Ks=0;
+
+			Vector3r segment = (Body::byId(interaction->getId1(),scene)->state->pos) - (Body::byId(interaction->getId2(),scene)->state->pos);
+			Real length = segment.norm();
+			Real pi = 3.14159265;
+			Real area = (pow(std::min(Db, Da),2))*pi;
+			Real iG = (pow(std::min(2*Db, 2*Da),4))*pi/32.;
+			Real iB = (pow(std::min(2*Db, 2*Da),4))*pi/64.;
+			// Ignacio Olmedo-Manich, non size-dependent mechanical params.
+			
+			contactPhysics->knT = ETT*area/length;
+			contactPhysics->knC = ETC*area/length;
+			contactPhysics->kt = GTw*iG/length;
+			contactPhysics->ks = 12*EB*iB/(pow(length,3));
+			contactPhysics->kr = EB*iB/length;
+			
+			contactPhysics->crpT = std::min(sdec1->creepT,sdec2->creepT);
+			contactPhysics->crpB = std::min(sdec1->creepB,sdec2->creepB);
+			contactPhysics->crpTw = std::min(sdec1->creepTw,sdec2->creepTw);
+			
+			contactPhysics->tangensOfFrictionAngle	= std::tan(std::min(fa,fb));
+			
+			contactPhysics->maxElastB = iB*std::min(sdec1->sigmaB,sdec2->sigmaB);
+			contactPhysics->maxElastTw = iB*std::min(sdec1->sigmaTw,sdec2->sigmaTw);
+						
+			contactPhysics->unldB = std::min(sdec1->unloadB,sdec2->unloadB);
+			contactPhysics->unldT = std::min(sdec1->unloadT,sdec2->unloadT);
+			contactPhysics->unldTw = std::min(sdec1->unloadTw,sdec2->unloadTw);
+			
+			contactPhysics->dElT = std::min(sdec1->disElT,sdec2->disElT);
+			contactPhysics->dElC = std::min(sdec1->disElC,sdec2->disElC);
+			
+			contactPhysics->epsMaxT = std::min(sdec1->epsilonMaxT,sdec2->epsilonMaxT);
+			contactPhysics->epsMaxC = std::min(sdec1->epsilonMaxC,sdec2->epsilonMaxC);
+			
+			contactPhysics->phBMax = std::min(sdec1->phiBMax,sdec2->phiBMax);
+			contactPhysics->phTwMax = std::min(sdec1->phiTwMax,sdec2->phiTwMax);
+			
+			if ((setCohesionOnNewContacts || setCohesionNow) && sdec1->isCohesive && sdec2->isCohesive)
+			{
+				contactPhysics->cohesionBroken = false;
+				contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(Db, Da),2);
+				contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(Db, Da),2);
+				geom->initRotations(*(Body::byId(interaction->getId1(),scene)->state),*(Body::byId(interaction->getId2(),scene)->state));
+			}
+					
+			//contactPhysics->elasticRollingLimit = elasticRollingLimit;
+		}
+		else {// !isNew, but if setCohesionNow, all contacts are initialized like if they were newly created
+			InelastCohFrictPhys* contactPhysics = YADE_CAST<InelastCohFrictPhys*>(interaction->phys.get());
+			if ((setCohesionNow && sdec1->isCohesive && sdec2->isCohesive) || contactPhysics->initCohesion)
+			{
+				contactPhysics->cohesionBroken = false;
+				contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(geom->radius2, geom->radius1),2);
+				contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(geom->radius2, geom->radius1),2);
+				geom->initRotations(*(Body::byId(interaction->getId1(),scene)->state),*(Body::byId(interaction->getId2(),scene)->state));
+				contactPhysics->initCohesion=false;
+			}
+		}
+	}
+};
+YADE_PLUGIN((Ip2_2xInelastCohFrictMat_InelastCohFrictPhys));
\ No newline at end of file

=== added file 'pkg/dem/Ip2_2xInelastCohFrictMat_InelastCohFrictPhys.hpp'
--- pkg/dem/Ip2_2xInelastCohFrictMat_InelastCohFrictPhys.hpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/Ip2_2xInelastCohFrictMat_InelastCohFrictPhys.hpp	2012-12-14 14:38:44 +0000
@@ -0,0 +1,26 @@
+#pragma once
+#include "Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.hpp"
+#include "InelastCohFrictMat.hpp"
+#include "InelastCohFrictPhys.hpp"
+#include<yade/pkg/dem/ScGeom.hpp>
+
+
+class Ip2_2xInelastCohFrictMat_InelastCohFrictPhys : public IPhysFunctor
+{
+	public :
+		virtual void go(	const shared_ptr<Material>& b1,
+					const shared_ptr<Material>& b2,
+					const shared_ptr<Interaction>& interaction);
+		int cohesionDefinitionIteration;
+
+		YADE_CLASS_BASE_DOC_ATTRS_CTOR(Ip2_2xInelastCohFrictMat_InelastCohFrictPhys,IPhysFunctor,
+		"Generates cohesive-frictional interactions with moments. Used in the contact law :yref:`Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment`.",
+		((bool,setCohesionNow,false,,"If true, assign cohesion to all existing contacts in current time-step. The flag is turned false automatically, so that assignment is done in the current timestep only."))
+		((bool,setCohesionOnNewContacts,false,,"If true, assign cohesion at all new contacts. If false, only existing contacts can be cohesive (also see :yref:`Ip2_CohFrictMat_CohFrictMat_CohFrictPhys::setCohesionNow`), and new contacts are only frictional."))	
+		,
+		cohesionDefinitionIteration = -1;
+		);
+	FUNCTOR2D(InelastCohFrictMat,InelastCohFrictMat);
+};
+
+REGISTER_SERIALIZABLE(Ip2_2xInelastCohFrictMat_InelastCohFrictPhys);
\ No newline at end of file

=== modified file 'pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.cpp'
--- pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.cpp	2012-10-09 09:09:02 +0000
+++ pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.cpp	2013-03-06 20:47:43 +0000
@@ -59,14 +59,8 @@
 			if ((setCohesionOnNewContacts || setCohesionNow) && sdec1->isCohesive && sdec2->isCohesive)
 			{
 				contactPhysics->cohesionBroken = false;
-				if (geom->cylCyl){
-					contactPhysics->normalAdhesion = std::min(sdec1->cylCylNormalCoh,sdec2->cylCylNormalCoh)*pow(std::min(Db, Da),2);
-					contactPhysics->shearAdhesion = std::min(sdec1->cylCylShearCoh,sdec2->cylCylShearCoh)*pow(std::min(Db, Da),2);
-				}
-				else{
-					contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(Db, Da),2);
-					contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(Db, Da),2);
-				}
+				contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(Db, Da),2);
+				contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(Db, Da),2);
 				geom->initRotations(*(Body::byId(interaction->getId1(),scene)->state),*(Body::byId(interaction->getId2(),scene)->state));
 			}
 			contactPhysics->kn = Kn;
@@ -81,14 +75,9 @@
 			if ((setCohesionNow && sdec1->isCohesive && sdec2->isCohesive) || contactPhysics->initCohesion)
 			{
 				contactPhysics->cohesionBroken = false;
-				if (geom->cylCyl){
-					contactPhysics->normalAdhesion = std::min(sdec1->cylCylNormalCoh,sdec2->cylCylNormalCoh)*pow(std::min(geom->radius2, geom->radius1),2);
-					contactPhysics->shearAdhesion = std::min(sdec1->cylCylShearCoh,sdec2->cylCylShearCoh)*pow(std::min(geom->radius2, geom->radius1),2);
-				}
-				else{
-					contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(geom->radius2, geom->radius1),2);
-					contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(geom->radius2, geom->radius1),2);
-				}
+				contactPhysics->normalAdhesion = std::min(sdec1->normalCohesion,sdec2->normalCohesion)*pow(std::min(geom->radius2, geom->radius1),2);
+				contactPhysics->shearAdhesion = std::min(sdec1->shearCohesion,sdec2->shearCohesion)*pow(std::min(geom->radius2, geom->radius1),2);
+
 				geom->initRotations(*(Body::byId(interaction->getId1(),scene)->state),*(Body::byId(interaction->getId2(),scene)->state));
 				contactPhysics->initCohesion=false;
 			}

=== modified file 'pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.hpp'
--- pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.hpp	2011-01-09 16:34:50 +0000
+++ pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.hpp	2013-01-14 21:22:11 +0000
@@ -20,7 +20,7 @@
 		int cohesionDefinitionIteration;
 
 		YADE_CLASS_BASE_DOC_ATTRS_CTOR(Ip2_CohFrictMat_CohFrictMat_CohFrictPhys,IPhysFunctor,
-		"Generates cohesive-frictional interactions with moments. Used in the contact law :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`.",
+		"Generates cohesive-frictional interactions with moments. Used in the contact law :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment`. The normal/shear stiffness and friction definitions are the same as in :yref:`Ip2_FrictMat_FrictMat_FrictPhys`, check the documentation there for details.",
 		((bool,setCohesionNow,false,,"If true, assign cohesion to all existing contacts in current time-step. The flag is turned false automatically, so that assignment is done in the current timestep only."))
 		((bool,setCohesionOnNewContacts,false,,"If true, assign cohesion at all new contacts. If false, only existing contacts can be cohesive (also see :yref:`Ip2_CohFrictMat_CohFrictMat_CohFrictPhys::setCohesionNow`), and new contacts are only frictional."))	
 		,

=== modified file 'pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.hpp'
--- pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.hpp	2012-06-04 21:03:29 +0000
+++ pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.hpp	2013-02-26 19:38:41 +0000
@@ -18,7 +18,7 @@
 			const shared_ptr<Material>& b2,
 			const shared_ptr<Interaction>& interaction);
 	FUNCTOR2D(FrictMat,FrictMat);
-	YADE_CLASS_BASE_DOC_ATTRS(Ip2_FrictMat_FrictMat_FrictPhys,IPhysFunctor,"Create a :yref:`FrictPhys` from two :yref:`FrictMats<FrictMat>`. The compliance of one sphere under symetric point loads is defined here as 1/(E.r), with E the stiffness of the sphere and r its radius, and corresponds to a compliance 1/(2.E.r)=1/(E.D) from each contact point. The compliance of the contact itself will be the sum of compliances from each sphere, i.e. 1/(E.D1)+1/(E.D2) in the general case, or 1/(E.r) in the special case of equal sizes. Note that summing compliances corresponds to an harmonic average of stiffnesss, which is how kn is actually computed in the :yref:`Ip2_FrictMat_FrictMat_FrictPhys` functor.\n\nThe shear stiffness ks of one sphere is defined via the material parameter :yref:`ElastMat::poisson`, as ks=poisson*kn, and the resulting shear stiffness of the interaction will be also an harmonic average.",
+	YADE_CLASS_BASE_DOC_ATTRS(Ip2_FrictMat_FrictMat_FrictPhys,IPhysFunctor,"Create a :yref:`FrictPhys` from two :yref:`FrictMats<FrictMat>`. The compliance of one sphere under point load is defined here as $1/(E.D)$, with $E$ the stiffness of the sphere and $D$ its diameter. The compliance of the contact itself will be the sum of compliances from each sphere, i.e. $1/(E_1.D_1)+1/(E_2.D_2)$ in the general case, or $2/(E.D)$ in the special case of equal sizes and equal stiffness. Note that summing compliances corresponds to an harmonic average of stiffnesss (as in e.g. [Scholtes2009a]_), which is how kn is actually computed in the :yref:`Ip2_FrictMat_FrictMat_FrictPhys` functor:\n\n $k_n = \\frac{E_1D_1*E_2D_2}{E_1D_1+E_2D_2}=\\frac{k_1*k_2}{k_1+k_2}$, with $k_i=E_iD_i$.\n\n The shear stiffness ks of one sphere is defined via the material parameter :yref:`ElastMat::poisson`, as ks=poisson*kn, and the resulting shear stiffness of the interaction will be also an harmonic average.",
 		((shared_ptr<MatchMaker>,frictAngle,,,"Instance of :yref:`MatchMaker` determining how to compute interaction's friction angle. If ``None``, minimum value is used."))
 	);
 };

=== modified file 'pkg/dem/L3Geom.cpp'
--- pkg/dem/L3Geom.cpp	2012-01-23 14:43:54 +0000
+++ pkg/dem/L3Geom.cpp	2013-03-07 18:28:01 +0000
@@ -291,7 +291,7 @@
 
 	// compute force
 	Vector3r& localF(geom->F);
-	localF=geom->relU().cwise()*Vector3r(phys->kn,phys->ks,phys->ks);
+	localF=geom->relU().cwiseProduct(Vector3r(phys->kn,phys->ks,phys->ks));
 	// break if necessary
 	if(localF[0]>0 && !noBreak){ scene->interactions->requestErase(I); return; }
 
@@ -304,10 +304,10 @@
 			Vector3r u0slip=(1-ratio)*Vector3r(/*no slip in the normal sense*/0,geom->relU()[1],geom->relU()[2]);
 			geom->u0+=u0slip; // increment plastic displacement
 			Fs*=ratio; // decrement shear force value;
-			if(unlikely(scene->trackEnergy)){ Real dissip=Fs.norm()*u0slip.norm(); if(dissip>0) scene->energy->add(dissip,"plastDissip",plastDissipIx,/*reset*/false); }
+			if(scene->trackEnergy){ Real dissip=Fs.norm()*u0slip.norm(); if(dissip>0) scene->energy->add(dissip,"plastDissip",plastDissipIx,/*reset*/false); }
 		}
 	}
-	if(unlikely(scene->trackEnergy)){ scene->energy->add(0.5*(pow(geom->relU()[0],2)*phys->kn+(pow(geom->relU()[1],2)+pow(geom->relU()[2],2))*phys->ks),"elastPotential",elastPotentialIx,/*reset at every timestep*/true); }
+	if(scene->trackEnergy)	{ scene->energy->add(0.5*(pow(geom->relU()[0],2)*phys->kn+(pow(geom->relU()[1],2)+pow(geom->relU()[2],2))*phys->ks),"elastPotential",elastPotentialIx,/*reset at every timestep*/true); }
 	// apply force: this converts the force to global space, updates NormShearPhys::{normal,shear}Force, applies to particles
 	geom->applyLocalForce(localF,I,scene,phys);
 }
@@ -317,8 +317,8 @@
 	L6Geom& geom=ig->cast<L6Geom>(); FrictPhys& phys=ip->cast<FrictPhys>();
 
 	// simple linear relationships
-	Vector3r localF=geom.relU().cwise()*Vector3r(phys.kn,phys.ks,phys.ks);
-	Vector3r localT=charLen*(geom.relPhi().cwise()*Vector3r(phys.kn,phys.ks,phys.ks));
+	Vector3r localF=geom.relU().cwiseProduct(Vector3r(phys.kn,phys.ks,phys.ks));
+	Vector3r localT=charLen*(geom.relPhi().cwiseProduct(Vector3r(phys.kn,phys.ks,phys.ks)));
 
 	geom.applyLocalForceTorque(localF,localT,I,scene,static_cast<NormShearPhys*>(ip.get()));
 }

=== added file 'pkg/dem/Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment.cpp'
--- pkg/dem/Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment.cpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment.cpp	2013-05-14 21:24:11 +0000
@@ -0,0 +1,279 @@
+#include "Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment.hpp"
+
+Real Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment::normElastEnergy()
+{
+	Real normEnergy=0;
+	FOREACH(const shared_ptr<Interaction>& I, *scene->interactions){
+		if(!I->isReal()) continue;
+		InelastCohFrictPhys* phys = YADE_CAST<InelastCohFrictPhys*>(I->phys.get());
+		if (phys) {
+			normEnergy += 0.5*(phys->normalForce.squaredNorm()/phys->kn);
+		}
+	}
+	return normEnergy;
+}
+Real Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment::shearElastEnergy()
+{
+	Real shearEnergy=0;
+	FOREACH(const shared_ptr<Interaction>& I, *scene->interactions){
+		if(!I->isReal()) continue;
+		InelastCohFrictPhys* phys = YADE_CAST<InelastCohFrictPhys*>(I->phys.get());
+		if (phys) {
+			shearEnergy += 0.5*(phys->shearForce.squaredNorm()/phys->ks);
+		}
+	}
+	return shearEnergy;
+}
+
+
+
+void Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment::go(shared_ptr<IGeom>& ig, shared_ptr<IPhys>& ip, Interaction* contact)
+{
+// 	cout<<"Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment"<<endl;
+	const Real& dt = scene->dt;
+	const int &id1 = contact->getId1();
+	const int &id2 = contact->getId2();
+	ScGeom6D* geom  = YADE_CAST<ScGeom6D*> (ig.get());
+	InelastCohFrictPhys* phys = YADE_CAST<InelastCohFrictPhys*> (ip.get());
+	Vector3r& shearForce    = phys->shearForce;
+			
+	cout<<"id1= "<<id1<<" id2= "<<id2<<endl;
+	
+	if (contact->isFresh(scene)) shearForce   = Vector3r::Zero();
+		
+	///Tension-Compresion///
+	
+	Real un     = geom->penetrationDepth;
+	Real Fn = phys->knT*(un);
+	//FIXME: Check signs on TESTS
+	State* de1 = Body::byId(id1,scene)->state.get();
+	State* de2 = Body::byId(id2,scene)->state.get();
+	
+	
+	if(!(phys->isBrokenT)){
+		
+		/// Tension ///
+		if(un<=0){
+			if((un>= -(phys->dElT)) && !onplastT){
+				Fn = phys->knT*(un);
+// 				cout<<"TENSION ELASTIC Fn= "<<Fn<<" un= "<<un<<endl;
+			}
+			if(un< -(phys->dElT) || onplastT){
+				onplastT = true;
+				Fn = phys->knT*(-phys->dElT) + phys->crpT*(un+phys->dElT);
+// 				cout<<"TENSION PLASTIC Fn= "<<Fn<<" un= "<<un<<" normalF= "<<phys->normalForce.norm()<<endl;
+				
+				if(phys->unloadedT ||(-phys->normalForce.norm()<=Fn)){
+					Fn = phys->knT*(-phys->dElT)+ phys->crpT*(lastPlastUn+phys->dElT) + phys->unldT*(un-lastPlastUn);
+					phys->unloadedT = true; 
+// 					cout<<"TENSION PLASTIC unloading Fn= "<<Fn<<" un= "<<un<<endl;
+					
+					if(un<=lastPlastUn){ // Recovers creep after unload and reload
+						phys->unloadedT=false;
+						Fn = phys->knT*(-phys->dElT) + phys->crpT*(un+phys->dElT);
+// 						cout<<"TENSION PLASTIC load aftr unld Fn= "<<Fn<<" un= "<<un<<" LPun= "<<lastPlastUn<<endl;
+					}
+					
+				} // Unloading::  //FIXME: ?? Check Fn Sign
+				else{// loading, applying Creeping
+					lastPlastUn = un;
+// 					cout<<"TENSION PLASTIC Creep Fn= "<<Fn<<" un= "<<un<<endl;
+					
+					if (un<-phys->epsMaxT){ // Plastic rupture //
+						Fn = 0.0;
+						phys->isBrokenT = true;  
+// 						cout<<"TENSION PLASTIC creep BROKEN Fn= "<<Fn<<" un= "<<un<<endl;
+					}
+				}  
+			}
+		}
+		/// Compresion ///
+		if(un>0){
+			if((un<=phys->dElC) && !onplastT){
+				Fn = phys->knC*(un);
+// 				cout<<"COMPRESION ELASTIC Fn= "<<Fn<<" un= "<<un<<endl;
+
+			}
+			if(un>phys->dElC || onplastT){
+				onplastT = true;
+				Fn = phys->knC*(phys->dElC) + phys->crpT*(un-phys->dElC);
+				if(phys->unloadedC || (phys->normalForce.norm()>=Fn)){
+					Fn = phys->knC*(phys->dElC)+ phys->crpT*(lastPlastUn-phys->dElC) + phys->unldT*(un-lastPlastUn);
+					phys->unloadedC = true; 
+// 					cout<<"COMPRESION PLASTIC unloading Fn= "<<Fn<<" un= "<<un<<endl;
+					
+					if(un>=lastPlastUn){ // Recovers creep after unload and reload
+						phys->unloadedC=false;
+						Fn = phys->knC*(phys->dElC) + phys->crpT*(un-phys->dElC);
+// 						cout<<"COMPRESION PLASTIC load aftr unld Fn= "<<Fn<<" un= "<<un<<" LPun= "<<lastPlastUn<<endl;
+					}
+				
+				} // Unloading::  //FIXME: Verify Fn Sign
+				else{// loading, applying Creeping
+					lastPlastUn = un;
+// 					cout<<"COMPRESION PLASTIC Creep Fn= "<<Fn<<" un= "<<un<<endl;
+					// Fn stills Fn = phys->crpT*(un-phys->unp) ;}
+					if (un>phys->epsMaxC){ // Plastic rupture //
+						Fn = 0.0;
+						phys->isBrokenT = true;  
+// 						cout<<"COMPRESION PLASTIC creep BROKEN Fn= "<<Fn<<" un= "<<un<<endl;
+					}
+				}  
+			}
+		}
+	phys->normalForce = Fn*geom->normal;
+	}
+// 	if ((-Fn)> phys->normalAdhesion) {//normal plasticity
+// 		Fn=-phys->normalAdhesion;
+// 		phys->unp = un+phys->normalAdhesion/phys->kn;
+// 		if (phys->unpMax && phys->unp<phys->unpMax)
+// 			scene->interactions->requestErase(contact); return;
+// 	}
+	
+	// 	cout<<"Tension-Comp normalF= "<<phys->normalForce<<endl;
+	///end tension-compression///
+	
+	///Shear/// ELASTOPLASTIC perfect law TO BE DONE
+	//FIXME:: TO DO::Shear ElastoPlastic perfect LAW  
+	///////////////////////// CREEP START ///////////
+	if (shear_creep) shearForce -= phys->ks*(shearForce*dt/creep_viscosity);
+	///////////////////////// CREEP END ////////////
+
+	shearForce = geom->rotate(phys->shearForce);
+	const Vector3r& dus = geom->shearIncrement();
+
+	//Linear elasticity giving "trial" shear force
+	shearForce -= phys->ks*dus;
+	
+	
+	Real Fs = phys->shearForce.norm();
+	Real maxFs = phys->shearAdhesion;
+	
+	
+	if (!phys->cohesionDisablesFriction || maxFs==0)
+		maxFs += Fn*phys->tangensOfFrictionAngle;
+		maxFs = std::max((Real) 0, maxFs);
+	if (Fs  > maxFs) {//Plasticity condition on shear force
+// 		cout<<"Plastshear ShearAdh= "<<phys->shearAdhesion<<endl;
+		if (phys->fragile && !phys->cohesionBroken) {
+			phys->SetBreakingState();
+			maxFs = max((Real) 0, Fn*phys->tangensOfFrictionAngle);
+		}
+		maxFs = maxFs / Fs;
+		Vector3r trialForce=shearForce;
+		shearForce *= maxFs;
+		if (scene->trackEnergy){
+			Real dissip=((1/phys->ks)*(trialForce-shearForce))/*plastic disp*/ .dot(shearForce)/*active force*/;
+			if(dissip>0) scene->energy->add(dissip,"plastDissip",plastDissipIx,/*reset*/false);}
+		if (Fn<0)  phys->normalForce = Vector3r::Zero();//Vector3r::Zero()
+	}
+// 	cout<<"Fs= "<<Fs<<" maxFs= "<<maxFs<<endl;
+
+	//Apply the force
+	applyForceAtContactPoint(-phys->normalForce-shearForce, geom->contactPoint, id1, de1->se3.position, id2, de2->se3.position + (scene->isPeriodic ? scene->cell->intrShiftPos(contact->cellDist): Vector3r::Zero()));
+// 		Vector3r force = -phys->normalForce-shearForce;
+// 		scene->forces.addForce(id1,force);
+// 		scene->forces.addForce(id2,-force);
+// 		scene->forces.addTorque(id1,(geom->radius1-0.5*geom->penetrationDepth)* geom->normal.cross(force));
+// 		scene->forces.addTorque(id2,(geom->radius2-0.5*geom->penetrationDepth)* geom->normal.cross(force));
+	/// end Shear ///
+	
+	/// Moment law  ///
+	/// Bending///
+	if(!(phys->isBrokenB)){
+		Vector3r relAngVel = geom->getRelAngVel(de1,de2,dt);
+		Vector3r relAngVelBend = relAngVel - geom->normal.dot(relAngVel)*geom->normal; // keep only the bending part
+		Vector3r relRotBend = relAngVelBend*dt; // relative rotation due to rolling behaviour	
+		Vector3r& momentBend = phys->moment_bending;
+		momentBend = geom->rotate(momentBend); // rotate moment vector (updated)
+
+		//To check if in elastic zone in current iteration
+		Real BendValue = (phys->moment_bending-phys->kr*relRotBend).norm();
+		Real MaxElastB = phys->maxElastB;
+		bool elasticBState = (BendValue<=MaxElastB);
+		
+		if(!onplastB && elasticBState){
+			momentBend = momentBend-phys->kr*relRotBend;
+// 			cout<<"BENDING Elastic"<<" momentB= "<<momentBend<<endl;
+		
+		}else{  ///Bending Plasticity///
+			onplastB = true;
+			BendValue = (phys->moment_bending-phys->crpB*relRotBend).norm();
+// 			cout<<"BENDING Plastic"<<" momentB= "<<momentBend<<endl;
+			// Unloading:: RelRotBend > 0 ::::
+			if(phys->unloadedB || phys->moment_bending.norm()>=BendValue){
+				momentBend = momentBend-phys->unldB*relRotBend;
+				phys->unloadedB = true; 
+// 				cout<<"BENDING Plastic UNLD"<<" momentB= "<<momentBend<<endl;
+				if(BendValue>=lastPlastBend){phys->unloadedB = false;} 
+				
+			} 
+			else{
+				momentBend = momentBend-phys->crpB*relRotBend;// loading, applying Creeping
+				Vector3r AbsRot = de1->rot()-de2->rot();
+				Real AbsBending = (AbsRot - geom->normal.dot(AbsRot)*geom->normal).norm();
+				lastPlastBend= BendValue;
+				if (AbsBending>phys->phBMax){ // Plastic rupture //FIXME: This line is not ok, need to find the compare the total(or just plastic) angular displacement to PhBmax, true meaning of relRotBend??
+					momentBend = Vector3r(0,0,0);
+					phys->isBrokenB = true;
+// 					cout<<"BENDING Plastic BREAK"<<" momentB= "<<momentBend<<endl;
+				}
+			}	
+		}
+		phys->moment_bending = momentBend;
+	}	
+	
+	///Twist///
+	
+	if(!(phys->isBrokenTw)){
+		Vector3r relAngVel = geom->getRelAngVel(de1,de2,dt);
+		Vector3r relAngVelTwist = geom->normal.dot(relAngVel)*geom->normal;
+		Vector3r relRotTwist = relAngVelTwist*dt; // component of relative rotation along n  FIXME: sign?
+		Vector3r& momentTwist = phys->moment_twist;
+		momentTwist = geom->rotate(momentTwist); // rotate moment vector (updated)
+		
+		//To check if in elastic zone in current iteration
+		Real TwistValue = (phys->moment_twist-phys->kt*relRotTwist).norm();
+		Real MaxElastTw = phys->maxElastTw;
+		bool elasticTwState = (TwistValue<=MaxElastTw);
+		
+		if (!onplastTw && elasticTwState){
+			momentTwist = momentTwist-phys->kt*relRotTwist; // FIXME: sign?
+// 			cout<<"TWIST Elast"<<" momentTwist="<<momentTwist<<endl;
+		}else {  ///Twist Plasticity///
+			onplastTw = true;
+			TwistValue = (phys->moment_twist-phys->crpTw*relRotTwist).norm();
+// 			cout<<"TWIST Plast"<<endl;
+			if (phys->unloadedTw || phys->moment_twist.norm()>=TwistValue){// Unloading:: RelRotTwist > 0 
+				momentTwist = momentTwist-phys->unldTw*relRotTwist;
+				phys->unloadedTw = true; 
+// 				cout<<"TWIST Plast UNLD"<<endl;
+				if(TwistValue>=lastPlastTw){phys->unloadedTw = false;} 
+			} 
+			    
+			else{momentTwist = momentTwist-phys->crpTw*relRotTwist;// loading, applying Creeping
+				Vector3r AbsRot = de1->rot()-de2->rot();
+				Real AbsTwist = (geom->normal.dot(AbsRot)*geom->normal).norm();
+				lastPlastTw= TwistValue;
+// 				cout<<"TWIST Creep momentTwist="<<momentTwist<<" AbsTwist="<<AbsTwist<<endl;
+				if (AbsTwist>phys->phTwMax){ // Plastic rupture //FIXME: This line is not ok, need to find the compare the total(or just plastic) angular displacement to PhBmax, true meaning of relRotBend??
+					momentTwist = Vector3r(0,0,0);
+					phys->isBrokenTw = true;
+				}
+			} 
+		}
+		phys->moment_twist = momentTwist;
+	}
+	
+// 	cout<<"moment Twist= "<<phys->moment_twist<<endl;
+
+	
+	// Apply moments now
+	Vector3r moment = phys->moment_twist + phys->moment_bending;
+	scene->forces.addTorque(id1,-moment);
+	scene->forces.addTorque(id2, moment);			
+	/// Moment law END ///
+
+}
+
+YADE_PLUGIN((Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment));

=== added file 'pkg/dem/Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment.hpp'
--- pkg/dem/Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment.hpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment.hpp	2013-05-14 21:24:11 +0000
@@ -0,0 +1,34 @@
+#pragma once
+#include "CohesiveFrictionalContactLaw.hpp"
+#include "InelastCohFrictPhys.hpp"
+
+class Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment: public LawFunctor{
+	public:
+		Real normElastEnergy();
+		Real shearElastEnergy();
+	virtual void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I);
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment,LawFunctor,"Law for linear traction-compression-bending-twisting, with cohesion+friction and Mohr-Coulomb plasticity surface. This law adds adhesion and moments to :yref:`Law2_ScGeom_FrictPhys_CundallStrack`.\n\nThe normal force is (with the convention of positive tensile forces) $F_n=min(k_n*u_n, a_n)$, with $a_n$ the normal adhesion. The shear force is $F_s=k_s*u_s$, the plasticity condition defines the maximum value of the shear force, by default $F_s^{max}=F_n*tan(\\phi)+a_s$, with $\\phi$ the friction angle and $a_n$ the shear adhesion. If :yref:`CohFrictPhys::cohesionDisableFriction` is True, friction is ignored as long as adhesion is active, and the maximum shear force is only $F_s^{max}=a_s$.\n\nIf the maximum tensile or maximum shear force is reached and :yref:`CohFrictPhys::fragile` =True (default), the cohesive link is broken, and $a_n, a_s$ are set back to zero. If a tensile force is present, the contact is lost, else the shear strength is $F_s^{max}=F_n*tan(\\phi)$. If :yref:`CohFrictPhys::fragile` =False (in course of implementation), the behaviour is perfectly plastic, and the shear strength is kept constant.\n\nIf :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment::momentRotationLaw` =True, bending and twisting moments are computed using a linear law with moduli respectively $k_t$ and $k_r$ (the two values are the same currently), so that the moments are : $M_b=k_b*\\Theta_b$ and $M_t=k_t*\\Theta_t$, with $\\Theta_{b,t}$ the relative rotations between interacting bodies. The maximum value of moments can be defined and takes the form of rolling friction. Cohesive -type moment may also be included in the future.\n\nCreep at contact is implemented in this law, as defined in [Hassan2010]_. If activated, there is a viscous behaviour of the shear and twisting components, and the evolution of the elastic parts of shear displacement and relative twist is given by $du_{s,e}/dt=-F_s/\\nu_s$ and $d\\Theta_{t,e}/dt=-M_t/\\nu_t$.",
+		((bool,neverErase,false,,"Keep interactions even if particles go away from each other (only in case another constitutive law is in the scene, e.g. :yref:`Law2_ScGeom_CapillaryPhys_Capillarity`)"))
+		((bool,always_use_moment_law,false,,"If true, use bending/twisting moments at all contacts. If false, compute moments only for cohesive contacts."))
+		((bool,shear_creep,false,,"activate creep on the shear force, using :yref:`CohesiveFrictionalContactLaw::creep_viscosity`."))
+		((bool,twist_creep,false,,"activate creep on the twisting moment, using :yref:`CohesiveFrictionalContactLaw::creep_viscosity`."))
+		((bool,useIncrementalForm,false,,"use the incremental formulation to compute bending and twisting moments. Creep on the twisting moment is not included in such a case."))
+		((int,plastDissipIx,-1,,"Index for plastic dissipation (with O.trackEnergy)"))
+		((bool,onplastB,false,,"true if plasticity achieved on bending"))
+		((bool,onplastTw,false,,"true if plasticity achieved on twisting"))
+		((bool,onplastT,false,,"true if plasticity achieved on traction/compression")) // if plasticity achieved in traction, also for later compression, and inverse
+		((Real,lastPlastUn,0,,"last tension compression un value of plasticity"))
+		((Real,lastPlastBend,0,,"last bend  value of plasticity"))
+		((Real,lastPlastTw,0,,"last bend  value of plasticity"))
+		((Real,unPrev,0,,"previous timestep penetrationDepth"))
+		((Real,creep_viscosity,1,,"creep viscosity [Pa.s/m]. probably should be moved to Ip2_CohFrictMat_CohFrictMat_CohFrictPhys."))
+		,,
+		.def("normElastEnergy",&Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment::normElastEnergy,"Compute normal elastic energy.")
+		.def("shearElastEnergy",&Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment::shearElastEnergy,"Compute shear elastic energy.")
+	);
+	FUNCTOR2D(ScGeom6D,InelastCohFrictPhys);
+	DECLARE_LOGGER;
+	private:
+	Real currentContactPhysics;
+};
+REGISTER_SERIALIZABLE(Law2_ScGeom6D_InelastCohFrictPhys_CohesionMoment);

=== modified file 'pkg/dem/Law2_ScGeom_CapillaryPhys_Capillarity.cpp'
--- pkg/dem/Law2_ScGeom_CapillaryPhys_Capillarity.cpp	2012-05-10 13:41:22 +0000
+++ pkg/dem/Law2_ScGeom_CapillaryPhys_Capillarity.cpp	2013-01-29 16:16:15 +0000
@@ -553,6 +553,7 @@
 
 bool BodiesMenisciiList::insert(const shared_ptr< Interaction >& interaction)
 {
+  checkLengthBuffer(interaction);
 	interactionsOnBody[interaction->getId1()].push_back(interaction);
 	interactionsOnBody[interaction->getId2()].push_back(interaction);
 	return true;
@@ -561,11 +562,19 @@
 
 bool BodiesMenisciiList::remove(const shared_ptr< Interaction >& interaction)
 {
+  checkLengthBuffer(interaction);
 	interactionsOnBody[interaction->getId1()].remove(interaction);
 	interactionsOnBody[interaction->getId2()].remove(interaction);
 	return true;
 }
 
+void BodiesMenisciiList::checkLengthBuffer(const shared_ptr<Interaction>& interaction) {
+	Body::id_t maxBodyId = std::max(interaction->getId1(), interaction->getId2());
+	if (unsigned(maxBodyId) >= interactionsOnBody.size()) {
+		interactionsOnBody.resize(maxBodyId+1);
+	}
+}
+
 list< shared_ptr<Interaction> >&  BodiesMenisciiList::operator[] (int index)
 {
 	return interactionsOnBody[index];

=== modified file 'pkg/dem/Law2_ScGeom_CapillaryPhys_Capillarity.hpp'
--- pkg/dem/Law2_ScGeom_CapillaryPhys_Capillarity.hpp	2011-11-30 13:30:02 +0000
+++ pkg/dem/Law2_ScGeom_CapillaryPhys_Capillarity.hpp	2013-01-29 16:16:15 +0000
@@ -70,13 +70,14 @@
 		
 	public:
 		BodiesMenisciiList();
-		BodiesMenisciiList(Scene* body);
-		bool prepare(Scene* scene);
-		bool insert(const shared_ptr<Interaction>& interaction);
-		bool remove(const shared_ptr<Interaction>& interaction);
-		list< shared_ptr<Interaction> >& operator[] (int index);
+		BodiesMenisciiList(Scene*);
+		bool prepare(Scene*);
+		bool insert(const shared_ptr<Interaction>&);
+		bool remove(const shared_ptr<Interaction>&);
+		list< shared_ptr<Interaction> >& operator[] (int);
 		int size();
 		void display();
+		void checkLengthBuffer(const shared_ptr<Interaction>&);
 		
 		
 		bool initialized;

=== modified file 'pkg/dem/NewtonIntegrator.cpp'
--- pkg/dem/NewtonIntegrator.cpp	2012-09-12 19:01:34 +0000
+++ pkg/dem/NewtonIntegrator.cpp	2013-05-14 21:24:11 +0000
@@ -25,13 +25,13 @@
 }
 
 Vector3r NewtonIntegrator::computeAccel(const Vector3r& force, const Real& mass, int blockedDOFs){
-	if(likely(blockedDOFs==0)) return (force/mass + gravity);
+	if(blockedDOFs==0) return (force/mass + gravity);
 	Vector3r ret(Vector3r::Zero());
 	for(int i=0; i<3; i++) if(!(blockedDOFs & State::axisDOF(i,false))) ret[i]+=force[i]/mass+gravity[i];
 	return ret;
 }
 Vector3r NewtonIntegrator::computeAngAccel(const Vector3r& torque, const Vector3r& inertia, int blockedDOFs){
-	if(likely(blockedDOFs==0)) return torque.cwise()/inertia;
+	if(blockedDOFs==0) return torque.cwiseQuotient(inertia);
 	Vector3r ret(Vector3r::Zero());
 	for(int i=0; i<3; i++) if(!(blockedDOFs & State::axisDOF(i,true))) ret[i]+=torque[i]/inertia[i];
 	return ret;
@@ -41,9 +41,9 @@
 	assert(b->isStandalone() || b->isClump());
 	// always positive dissipation, by-component: |F_i|*|v_i|*damping*dt (|T_i|*|ω_i|*damping*dt for rotations)
 	if(damping!=0. && state->isDamped){
-		scene->energy->add(fluctVel.cwise().abs().dot(f.cwise().abs())*damping*scene->dt,"nonviscDamp",nonviscDampIx,/*non-incremental*/false);
+		scene->energy->add(fluctVel.cwiseAbs().dot(f.cwiseAbs())*damping*scene->dt,"nonviscDamp",nonviscDampIx,/*non-incremental*/false);
 		// when the aspherical integrator is used, torque is damped instead of ang acceleration; this code is only approximate
-		scene->energy->add(state->angVel.cwise().abs().dot(m.cwise().abs())*damping*scene->dt,"nonviscDamp",nonviscDampIx,false);
+		scene->energy->add(state->angVel.cwiseAbs().dot(m.cwiseAbs())*damping*scene->dt,"nonviscDamp",nonviscDampIx,false);
 	}
 	// kinetic energy
 	Real Etrans=.5*state->mass*fluctVel.squaredNorm();
@@ -53,9 +53,11 @@
 		Matrix3r mI; mI<<state->inertia[0],0,0, 0,state->inertia[1],0, 0,0,state->inertia[2];
 		Matrix3r T(state->ori);
 		Erot=.5*b->state->angVel.transpose().dot((T.transpose()*mI*T)*b->state->angVel);
-	} else { Erot=0.5*state->angVel.dot(state->inertia.cwise()*state->angVel); }
+	} else { Erot=0.5*state->angVel.dot(state->inertia.cwiseProduct(state->angVel)); }
 	if(!kinSplit) scene->energy->add(Etrans+Erot,"kinetic",kinEnergyIx,/*non-incremental*/true);
 	else{ scene->energy->add(Etrans,"kinTrans",kinEnergyTransIx,true); scene->energy->add(Erot,"kinRot",kinEnergyRotIx,true); }
+	// gravitational work (work done by gravity is "negative", since the energy appears in the system from outside)
+	scene->energy->add(-gravity.dot(b->state->vel)*b->state->mass*scene->dt,"gravWork",fieldWorkIx,/*non-incremental*/false);
 }
 
 void NewtonIntegrator::saveMaximaVelocity(const Body::id_t& id, State* state){
@@ -87,7 +89,7 @@
 {
 	if (syncEnsured) return;	
 	YADE_PARALLEL_FOREACH_BODY_BEGIN(const shared_ptr<Body>& b, scene->bodies){
-		if(b->isClump()) continue;
+// 		if(b->isClump()) continue;
 		scene->forces.addForce(b->getId(),Vector3r(0,0,0));
 	} YADE_PARALLEL_FOREACH_BODY_END();
 	syncEnsured=true;
@@ -105,6 +107,8 @@
 	bodySelected=(scene->selectedBody>=0);
 	if(warnNoForceReset && scene->forces.lastReset<scene->iter) LOG_WARN("O.forces last reset in step "<<scene->forces.lastReset<<", while the current step is "<<scene->iter<<". Did you forget to include ForceResetter in O.engines?");
 	const Real& dt=scene->dt;
+	//Take care of user's request to change velGrad. Safe to change it here after the interaction loop.
+	if (scene->cell->velGradChanged) {scene->cell->velGrad=scene->cell->nextVelGrad; scene->cell->velGradChanged=0;}
 	homoDeform=scene->cell->homoDeform;
 	dVelGrad=scene->cell->velGrad-prevVelGrad;
 	// account for motion of the periodic boundary, if we remember its last position
@@ -134,14 +138,14 @@
 	#endif
 	YADE_PARALLEL_FOREACH_BODY_BEGIN(const shared_ptr<Body>& b, scene->bodies){
 			// clump members are handled inside clumps
-			if(unlikely(b->isClumpMember())) continue;
+			if(b->isClumpMember()) continue;
 			State* state=b->state.get(); const Body::id_t& id=b->getId();
 			Vector3r f=Vector3r::Zero(), m=Vector3r::Zero();
 			// clumps forces
 			if(b->isClump()) {
 				b->shape->cast<Clump>().addForceTorqueFromMembers(state,scene,f,m);
 				#ifdef YADE_OPENMP
-				//it is safe here, since onky one thread will read/write
+				//it is safe here, since only one thread will read/write
 				scene->forces.getTorqueUnsynced(id)+=m;
 				scene->forces.getForceUnsynced(id)+=f;
 				#else
@@ -163,7 +167,7 @@
 			Vector3r fluctVel=isPeriodic?scene->cell->bodyFluctuationVel(b->state->pos,b->state->vel,prevVelGrad):state->vel;
 
 			// numerical damping & kinetic energy
-			if(unlikely(trackEnergy)) updateEnergy(b,state,fluctVel,f,m);
+			if(trackEnergy) updateEnergy(b,state,fluctVel,f,m);
 
 			// whether to use aspherical rotation integration for this body; for no accelerations, spherical integrator is "exact" (and faster)
 			bool useAspherical=(exactAsphericalRot && b->isAspherical() && state->blockedDOFs!=State::DOF_ALL);
@@ -210,7 +214,7 @@
 	#ifdef YADE_OPENMP
 		FOREACH(const Real& thrMaxVSq, threadMaxVelocitySq) { maxVelocitySq=max(maxVelocitySq,thrMaxVSq); }
 	#endif
-	if(scene->isPeriodic) { prevCellSize=scene->cell->getSize(); prevVelGrad=scene->cell->velGrad; }
+	if(scene->isPeriodic) { prevCellSize=scene->cell->getSize(); prevVelGrad=scene->cell->prevVelGrad=scene->cell->velGrad; }
 }
 
 void NewtonIntegrator::leapfrogTranslate(State* state, const Body::id_t& id, const Real& dt){
@@ -244,13 +248,13 @@
 	Matrix3r A=state->ori.conjugate().toRotationMatrix(); // rotation matrix from global to local r.f.
 	const Vector3r l_n = state->angMom + dt/2. * M; // global angular momentum at time n
 	const Vector3r l_b_n = A*l_n; // local angular momentum at time n
-	Vector3r angVel_b_n = l_b_n.cwise()/state->inertia; // local angular velocity at time n
+	Vector3r angVel_b_n = l_b_n.cwiseQuotient(state->inertia); // local angular velocity at time n
 	if (densityScaling) angVel_b_n*=state->densityScaling;
 	const Quaternionr dotQ_n=DotQ(angVel_b_n,state->ori); // dQ/dt at time n
 	const Quaternionr Q_half = state->ori + dt/2. * dotQ_n; // Q at time n+1/2
 	state->angMom+=dt*M; // global angular momentum at time n+1/2
 	const Vector3r l_b_half = A*state->angMom; // local angular momentum at time n+1/2
-	Vector3r angVel_b_half = l_b_half.cwise()/state->inertia; // local angular velocity at time n+1/2
+	Vector3r angVel_b_half = l_b_half.cwiseQuotient(state->inertia); // local angular velocity at time n+1/2
 	if (densityScaling) angVel_b_half*=state->densityScaling;
 	const Quaternionr dotQ_half=DotQ(angVel_b_half,Q_half); // dQ/dt at time n+1/2
 	state->ori=state->ori+dt*dotQ_half; // Q at time n+1
@@ -268,12 +272,9 @@
 bool NewtonIntegrator::get_densityScaling() {
 	FOREACH(const shared_ptr<Engine> e, Omega::instance().getScene()->engines) {
 		GlobalStiffnessTimeStepper* ts=dynamic_cast<GlobalStiffnessTimeStepper*>(e.get());
-		if (ts) {
-			if (densityScaling != ts->densityScaling) LOG_ERROR("inconsistent set of densityScaling in Newton and TimeStepper, did you change the TimeStepper's value?");
-			return ts->densityScaling;
-		}
-	} LOG_ERROR("Density scaling needs GlobalStiffnessTimeStepper present in O.engines.");
-	return 0;
+		if (ts && densityScaling != ts->densityScaling) LOG_WARN("density scaling is not active in the timeStepper, it will have no effect unless a scaling is specified manually for some bodies");}
+	LOG_WARN("GlobalStiffnessTimeStepper not present in O.engines, density scaling will have no effect unless a scaling is specified manually for some bodies");
+	return densityScaling;;
 }
 
 void NewtonIntegrator::set_densityScaling(bool dsc) {
@@ -282,9 +283,10 @@
 		if (ts) {
 			ts->densityScaling=dsc;
 			densityScaling=dsc;
+			LOG_WARN("GlobalStiffnessTimeStepper found in O.engines and adjusted to match this setting. Revert in the the timestepper if you don't want the scaling adjusted automatically.");
 			return;
 		}
-	} LOG_ERROR("Density scaling needs GlobalStiffnessTimeStepper present in O.engines. Not set.");
+	} LOG_WARN("GlobalStiffnessTimeStepper not found in O.engines. Density scaling will have no effect unless a scaling is specified manually for some bodies");
 }
 
 

=== modified file 'pkg/dem/NewtonIntegrator.hpp'
--- pkg/dem/NewtonIntegrator.hpp	2012-08-23 22:54:30 +0000
+++ pkg/dem/NewtonIntegrator.hpp	2013-05-14 21:24:11 +0000
@@ -7,7 +7,7 @@
 *************************************************************************/
 #pragma once
 
-#include<yade/core/GlobalEngine.hpp>
+#include<yade/pkg/common/FieldApplier.hpp>
 #include<yade/core/Interaction.hpp>
 #include<yade/lib/base/Math.hpp>
 #include<yade/pkg/common/Callbacks.hpp>
@@ -22,7 +22,7 @@
  */
 class State;
 
-class NewtonIntegrator : public GlobalEngine{
+class NewtonIntegrator : public FieldApplier{
 	inline void cundallDamp1st(Vector3r& force, const Vector3r& vel);
 	inline void cundallDamp2nd(const Real& dt, const Vector3r& vel, Vector3r& accel);
 	inline void leapfrogTranslate(State*, const Body::id_t& id, const Real& dt); // leap-frog translate
@@ -83,7 +83,7 @@
 				threadMaxVelocitySq.resize(omp_get_max_threads()); syncEnsured=false;
 			#endif
 		,/*py*/
-		.add_property("densityScaling",&NewtonIntegrator::get_densityScaling,&NewtonIntegrator::set_densityScaling,"if True, then density scaling [Pfc3dManual30]_ will be applied in order to have a critical timestep equal to :yref:`GlobalStiffnessTimeStepper::targetDt` for all bodies. This option makes the simulation unrealistic from a dynamic point of view, but may speedup quasistatic simulations.")
+		.add_property("densityScaling",&NewtonIntegrator::get_densityScaling,&NewtonIntegrator::set_densityScaling,"if True, then density scaling [Pfc3dManual30]_ will be applied in order to have a critical timestep equal to :yref:`GlobalStiffnessTimeStepper::targetDt` for all bodies. This option makes the simulation unrealistic from a dynamic point of view, but may speedup quasistatic simulations. In rare situations, it could be useful to not set the scalling factor automatically for each body (which the time-stepper does). In such case revert :yref:`GlobalStiffnessTimeStepper.densityScaling` to False.")
 	);
 	DECLARE_LOGGER;
 };

=== modified file 'pkg/dem/PeriIsoCompressor.cpp'
--- pkg/dem/PeriIsoCompressor.cpp	2012-09-08 01:19:45 +0000
+++ pkg/dem/PeriIsoCompressor.cpp	2013-05-03 16:45:52 +0000
@@ -213,8 +213,8 @@
 		//-bogusPoisson*(cellGrow[ax1]/refSize[ax1])*(stiff[ax1]/cellArea[ax1])-bogusPoisson*(cellGrow[ax2]/refSize[ax2])*(stiff[ax2]/cellArea[ax2]);
 	}
  	for (int k=0;k<3;k++) strainRate[k]=scene->cell->velGrad(k,k);
-	//Update energy input
-	Real dW=(scene->cell->velGrad*stressTensor).trace()*scene->dt*scene->cell->hSize.determinant();
+	//Update energy input FIXME: replace trace by norm, so it works for any kind of deformation
+	Real dW=(0.5*(scene->cell->prevVelGrad + scene->cell->velGrad)*stressTensor).trace()*scene->dt*(scene->cell->hSize.determinant());
 	externalWork+=dW;
 	if(scene->trackEnergy) scene->energy->add(-dW,"velGradWork",velGradWorkIx,/*non-incremental*/false);
 	prevGrow = strainRate;
@@ -374,7 +374,7 @@
 			//for (int i=0; i<lenPs; i++) { strainRate(ps(i)) -= maxStrainRate; }
 		}
 		else { // actual predictor
-			Real sr=strainRate.cwise().abs().maxCoeff();
+			Real sr=strainRate.cwiseAbs().maxCoeff();
 			for (int i=0; i<lenPs; i++) {
 				int j=ps(i);
 				// linear extrapolation of stress error (difference between actual and ideal stress)
@@ -387,7 +387,7 @@
 	}
 
 	// correction coefficient ix strainRate.maxabs() > maxStrainRate
-	Real srCorr = (strainRate.cwise().abs().maxCoeff() > maxStrainRate)? (maxStrainRate/strainRate.cwise().abs().maxCoeff()):1.;
+	Real srCorr = (strainRate.cwiseAbs().maxCoeff() > maxStrainRate)? (maxStrainRate/strainRate.cwiseAbs().maxCoeff()):1.;
 	strainRate *= srCorr;
 
 	// Actual action (see the documentation for more info)
@@ -401,13 +401,14 @@
 	   multiplying by time to obtain strain increment and adding it to nonrot (current strain in local coordinates)*/
 	nonrot += rot.transpose()*(epsilonRate*dt)*rot;
 	Matrix3r& velGrad=scene->cell->velGrad;
-	// compute new trsf as rot*nonrot, substract actual trsf (= trsf increment), divide by dt (=trsf rate = velGrad
-	//trsf = rot*nonrot;
-	//velGrad = (rot*nonrot - trsf)/dt;
+	// compute velGrad:
+	//   trsf = rot*nonrot
+	//   dTrsf = dt*velGrad
+	//   trsfNew = trsf + dTrsf*trsf = (I+dTrsf)*trsf = (I+dt*velGrad)*trsf   ->   velGrad
 	velGrad = ((rot*nonrot)*trsf.inverse()- Matrix3r::Identity()) / dt ;
 	progress += srCorr/nSteps;
 
-	if (progress >= 1. || strain.cwise().abs().maxCoeff() > maxStrain) {
+	if (progress >= 1. || strain.cwiseAbs().maxCoeff() > maxStrain) {
 		if(doneHook.empty()){ LOG_INFO("No doneHook set, dying."); dead=true; Omega::instance().pause(); }
 		else{ LOG_INFO("Running doneHook: "<<doneHook);	pyRunString(doneHook);}
 	}

=== modified file 'pkg/dem/SampleCapillaryPressureEngine.cpp'
--- pkg/dem/SampleCapillaryPressureEngine.cpp	2010-11-19 12:30:08 +0000
+++ pkg/dem/SampleCapillaryPressureEngine.cpp	2013-02-07 18:12:42 +0000
@@ -1,3 +1,5 @@
+#ifdef DEPREC_CODE
+
 /*************************************************************************
 *  Copyright (C) 2006 by Luc Scholtes                                    *
 *  luc.scholtes@xxxxxxxxxxx                                              *
@@ -72,3 +74,4 @@
 		UnbalancedForce = ComputeUnbalancedForce(scene);
 }
 
+#endif //DEPREC CODE
\ No newline at end of file

=== modified file 'pkg/dem/SampleCapillaryPressureEngine.hpp'
--- pkg/dem/SampleCapillaryPressureEngine.hpp	2012-11-22 14:32:53 +0000
+++ pkg/dem/SampleCapillaryPressureEngine.hpp	2013-02-07 18:12:42 +0000
@@ -1,3 +1,4 @@
+#ifdef DEPREC_CODE
 /*************************************************************************
 *  Copyright (C) 2006 by Luc Scholtes                                    *
 *  luc.scholtes@xxxxxxxxxxx                                              *
@@ -53,5 +54,5 @@
 
 #endif //  SAMPLECAPILLARYPRESSUREENGINE_HPP
 
-
+#endif //DEPREC CODE
 

=== modified file 'pkg/dem/ScGeom.hpp'
--- pkg/dem/ScGeom.hpp	2012-10-12 09:54:33 +0000
+++ pkg/dem/ScGeom.hpp	2013-03-06 20:47:43 +0000
@@ -14,7 +14,6 @@
  */
 
 #define SCG_SHEAR
-#define IGCACHE
 
 class ScGeom: public GenericSpheresContact {
 	private:
@@ -76,7 +75,6 @@
 		((Quaternionr,twistCreep,Quaternionr(1.0,0.0,0.0,0.0),(Attr::readonly),"Stored creep, substracted from total relative rotation for computation of elastic moment |yupdate|"))
 		((Real,twist,0,(Attr::noSave | Attr::readonly),"Elastic twist angle of the contact."))
 		((Vector3r,bending,Vector3r::Zero(),(Attr::noSave | Attr::readonly),"Bending at contact as a vector defining axis of rotation and angle (angle=norm)."))
-		((bool, cylCyl,0,(Attr::hidden),"True if the contact geometry is between two DIFFERENT chainedCylinders."))
 		,
 		/* extra initializers */,
 		/* ctor */ createIndex();,

=== modified file 'pkg/dem/Shop.cpp'
--- pkg/dem/Shop.cpp	2012-11-13 14:32:37 +0000
+++ pkg/dem/Shop.cpp	2013-03-19 09:58:00 +0000
@@ -39,6 +39,7 @@
 #include<yade/pkg/dem/ScGeom.hpp>
 #include<yade/pkg/dem/FrictPhys.hpp>
 
+#include<yade/pkg/common/Grid.hpp>
 
 #include<yade/pkg/dem/Tetra.hpp>
 
@@ -206,7 +207,7 @@
 			Matrix3r mI; mI<<state->inertia[0],0,0, 0,state->inertia[1],0, 0,0,state->inertia[2];
 			E+=.5*state->angVel.transpose().dot((T.transpose()*mI*T)*state->angVel);
 		}
-		else { E+=0.5*state->angVel.dot(state->inertia.cwise()*state->angVel);}
+		else { E+=0.5*state->angVel.dot(state->inertia.cwiseProduct(state->angVel));}
 		if(maxId && E>maxE) { *maxId=b->getId(); maxE=E; }
 		ret+=E;
 	}
@@ -382,15 +383,16 @@
 	return ( std::pow(S,3) - Vv ) / std::pow(S,3);
 };
 
-vector<pair<Vector3r,Real> > Shop::loadSpheresFromFile(const string& fname, Vector3r& minXYZ, Vector3r& maxXYZ, Vector3r* cellSize){
+vector<tuple<Vector3r,Real,int> > Shop::loadSpheresFromFile(const string& fname, Vector3r& minXYZ, Vector3r& maxXYZ, Vector3r* cellSize){
 	if(!boost::filesystem::exists(fname)) {
 		throw std::invalid_argument(string("File with spheres `")+fname+"' doesn't exist.");
 	}
-	vector<pair<Vector3r,Real> > spheres;
+	vector<tuple<Vector3r,Real,int> > spheres;
 	ifstream sphereFile(fname.c_str());
 	if(!sphereFile.good()) throw std::runtime_error("File with spheres `"+fname+"' couldn't be opened.");
 	Vector3r C;
 	Real r=0;
+	int clumpId=-1;
 	string line;
 	size_t lineNo=0;
 	while(std::getline(sphereFile, line, '\n')){
@@ -403,11 +405,12 @@
 			if(cellSize){ *cellSize=Vector3r(lexical_cast<Real>(tokens[1]),lexical_cast<Real>(tokens[2]),lexical_cast<Real>(tokens[3])); }
 			continue;
 		}
-		if(tokens.size()!=4) throw std::invalid_argument(("Line "+lexical_cast<string>(lineNo)+" in the spheres file "+fname+" has "+lexical_cast<string>(tokens.size())+" columns (must be 4).").c_str());
+		if(tokens.size()!=5 and tokens.size()!=4) throw std::invalid_argument(("Line "+lexical_cast<string>(lineNo)+" in the spheres file "+fname+" has "+lexical_cast<string>(tokens.size())+" columns (must be 4 or 5).").c_str());
 		C=Vector3r(lexical_cast<Real>(tokens[0]),lexical_cast<Real>(tokens[1]),lexical_cast<Real>(tokens[2]));
 		r=lexical_cast<Real>(tokens[3]);
 		for(int j=0; j<3; j++) { minXYZ[j]=(spheres.size()>0?min(C[j]-r,minXYZ[j]):C[j]-r); maxXYZ[j]=(spheres.size()>0?max(C[j]+r,maxXYZ[j]):C[j]+r);}
-		spheres.push_back(pair<Vector3r,Real>(C,r));
+		if(tokens.size()==5)clumpId=lexical_cast<int>(tokens[4]);
+		spheres.push_back(tuple<Vector3r,Real,int>(C,r,clumpId));
 	}
 	return spheres;
 }
@@ -764,8 +767,11 @@
 	const bool isPeriodic = scene->isPeriodic;
 	FOREACH(const shared_ptr<Interaction>&I, *scene->interactions){
 		if (!I->isReal()) continue;
+		shared_ptr<Body> b1 = Body::byId(I->getId1(),scene);
+		shared_ptr<Body> b2 = Body::byId(I->getId2(),scene);
+		if (b1->shape->getClassIndex()==GridNode::getClassIndexStatic()) continue; //no need to check b2 because a GridNode can only be in interaction with an oher GridNode.
 		NormShearPhys* nsi=YADE_CAST<NormShearPhys*> ( I->phys.get() );
-		Vector3r branch=Body::byId(I->getId1(),scene)->state->pos -Body::byId(I->getId2(),scene)->state->pos;
+		Vector3r branch=b1->state->pos -b2->state->pos;
 		if (isPeriodic) branch-= scene->cell->hSize*I->cellDist.cast<Real>();
 		stressTensor += (nsi->normalForce+nsi->shearForce)*branch.transpose();
 	}
@@ -830,11 +836,13 @@
 	const shared_ptr<Scene> scene=(_scene?_scene:Omega::instance().getScene());
 	FOREACH(shared_ptr<Body> b, *scene->bodies){
 		if (!b || !b->isDynamic()) continue;
+		if(((mask>0) and ((b->groupMask & mask)==0))) continue;
 		Sphere* s=dynamic_cast<Sphere*>(b->shape.get());
-		if((!s) or ((mask>0) and ((b->groupMask & mask)==0))) continue;
-		b->state->vel=Vector3r::Zero();
-		b->state->angVel=Vector3r::Zero();
-		b->state->angMom=Vector3r::Zero();
+		if ( (s) or ( (!s) && (b->isClump()) ) ){
+			b->state->vel=Vector3r::Zero();
+			b->state->angVel=Vector3r::Zero();
+			b->state->angMom=Vector3r::Zero();
+		}
 	}
 }
 
@@ -877,15 +885,23 @@
 {
 	Scene* scene = Omega::instance().getScene().get();
 	FOREACH(const shared_ptr<Body>& b,*scene->bodies){
-		if (dynamicOnly && !b->isDynamic() && !b->isClumpMember()) continue;
+		if (dynamicOnly && !b->isDynamic()) continue;
+		int ci=b->shape->getClassIndex();
+		if(b->isClump() || ci==GridNode::getClassIndexStatic() || ci==GridConnection::getClassIndexStatic()) continue;
 		if (updateMass) {b->state->mass*=pow(multiplier,3); b->state->inertia*=pow(multiplier,5);}
-		if(b->isClump()) continue;
 		(YADE_CAST<Sphere*> (b->shape.get()))->radius *= multiplier;
 		// Clump volume variation with homothetic displacement from its center
 		if (b->isClumpMember()) b->state->pos += (multiplier-1) * (b->state->pos - Body::byId(b->clumpId, scene)->state->pos);
 	}
-
+	FOREACH(const shared_ptr<Body>& b,*scene->bodies){
+		if(b->isClump()){
+			Clump* clumpSt = YADE_CAST<Clump*>(b->shape.get());
+			clumpSt->updateProperties(b, 0);
+		}
+	}
 	FOREACH(const shared_ptr<Interaction>& ii, *scene->interactions){
+		int ci=(*(scene->bodies))[ii->getId1()]->shape->getClassIndex();
+		if(ci==GridNode::getClassIndexStatic() || ci==GridConnection::getClassIndexStatic()) continue;
 		if (ii->isReal()) {
 			GenericSpheresContact* contact = YADE_CAST<GenericSpheresContact*>(ii->geom.get());
 			if (!dynamicOnly || (*(scene->bodies))[ii->getId1()]->isDynamic())

=== modified file 'pkg/dem/Shop.hpp'
--- pkg/dem/Shop.hpp	2012-11-13 14:32:37 +0000
+++ pkg/dem/Shop.hpp	2013-01-07 15:19:31 +0000
@@ -47,7 +47,7 @@
 		static shared_ptr<FrictMat> defaultGranularMat();
 
 		//! Return vector of pairs (center,radius) loaded from a file with numbers inside
-		static vector<pair<Vector3r,Real> > loadSpheresFromFile(const string& fname,Vector3r& minXYZ, Vector3r& maxXYZ, Vector3r* cellSize=NULL);
+		static vector<tuple<Vector3r,Real,int> > loadSpheresFromFile(const string& fname,Vector3r& minXYZ, Vector3r& maxXYZ, Vector3r* cellSize=NULL);
 		
 		//! Save spheres in the current simulation into a text file
 		static void saveSpheresToFile(string fileName);

=== modified file 'pkg/dem/SpherePack.cpp'
--- pkg/dem/SpherePack.cpp	2012-02-14 16:58:21 +0000
+++ pkg/dem/SpherePack.cpp	2013-03-07 18:28:01 +0000
@@ -51,12 +51,12 @@
 };
 
 void SpherePack::fromFile(string file) {
-	typedef pair<Vector3r,Real> pairVector3rReal;
-	vector<pairVector3rReal> ss;
+	typedef tuple<Vector3r,Real,int> tupleVector3rRealInt;
+	vector<tupleVector3rRealInt> ss;
 	Vector3r mn,mx;
 	ss=Shop::loadSpheresFromFile(file,mn,mx,&cellSize);
 	pack.clear();
-	FOREACH(const pairVector3rReal& s, ss) pack.push_back(Sph(s.first,s.second));
+	FOREACH(const tupleVector3rRealInt& s, ss) pack.push_back(Sph(get<0>(s),get<1>(s),get<2>(s)));
 }
 
 void SpherePack::toFile(const string fname) const {
@@ -64,8 +64,8 @@
 	if(!f.good()) throw runtime_error("Unable to open file `"+fname+"'");
 	if(cellSize!=Vector3r::Zero()){ f<<"##PERIODIC:: "<<cellSize[0]<<" "<<cellSize[1]<<" "<<cellSize[2]<<endl; }
 	FOREACH(const Sph& s, pack){
-		if(s.clumpId>=0) throw std::invalid_argument("SpherePack with clumps cannot be (currently) exported to a text file.");
-		f<<s.c[0]<<" "<<s.c[1]<<" "<<s.c[2]<<" "<<s.r<<endl;
+		//if(s.clumpId>=0) throw std::invalid_argument("SpherePack with clumps cannot be (currently) exported to a text file.");
+		f<<s.c[0]<<" "<<s.c[1]<<" "<<s.c[2]<<" "<<s.r<<" "<<s.clumpId<<endl;
 	}
 	f.close();
 };
@@ -100,7 +100,7 @@
 	Matrix3r invHsize =hSize.inverse();
 	Real area=abs(size[0]*size[2]+size[0]*size[1]+size[1]*size[2]);//2 terms will be null if one coordinate is 0, the other is the area
 	if (!volume) {
-		if (hSizeFound || !periodic) throw invalid_argument("The box as null volume, this is not supported. One exception is for flat box defined by min-max in periodic conditions, if hSize argument defines a non-null volume (or if the hSize argument is left undefined).");
+		if (hSizeFound) throw invalid_argument("The period defined by hSize has null length in at least one direction, this is not supported. Define flat boxes via min-max and keep hSize undefined if you want a 2D packing.");
 		else LOG_WARN("The volume of the min-max box is null, we will assume that the packing is 2D. If it is not what you want then you defined wrong input values; check that min and max corners are defined correctly.");}
 	int mode=-1; bool err=false;
 	// determine the way we generate radii
@@ -163,7 +163,8 @@
 		int t;
 		switch(mode){
 			case RDIST_RMEAN:
-			//FIXME : r is never defined, it will be zero at first iteration, but it will have values in the next ones. Some magic?
+			//FIXME : r is never defined, it will be zero at first iteration, but it will have values in the next ones.
+			//I don't understand why it apparently works. Some magic?
 			case RDIST_NUM:
 				if(distributeMass) r=pow3Interp(rand,rMean*(1-rRelFuzz),rMean*(1+rRelFuzz));
 				else r=rMean*(2*(rand-.5)*rRelFuzz+1); // uniform distribution in rMean*(1±rRelFuzz)
@@ -425,7 +426,7 @@
 	return pack.size();
 }
 
-long SpherePack::makeClumpCloud(const Vector3r& mn, const Vector3r& mx, const vector<shared_ptr<SpherePack> >& _clumps, bool periodic, int num){
+long SpherePack::makeClumpCloud(const Vector3r& mn, const Vector3r& mx, const vector<shared_ptr<SpherePack> >& _clumps, bool periodic, int num, int seed){
 	// recenter given clumps and compute their margins
 	vector<SpherePack> clumps; /* vector<Vector3r> margins; */ Vector3r boxMargins(Vector3r::Zero()); Real maxR=0;
 	vector<Real> boundRad; // squared radii of bounding sphere for each clump
@@ -447,7 +448,7 @@
 	const int maxTry=200;
 	int nGen=0; // number of clumps generated
 	// random point coordinate generator, with non-zero margins if aperiodic
-	static boost::minstd_rand randGen(TimingInfo::getNow(true));
+	static boost::minstd_rand randGen(seed!=0?seed:(int)TimingInfo::getNow(/* get the number even if timing is disabled globally */ true));
 	typedef boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > UniRandGen;
 	static UniRandGen rndX(randGen,boost::uniform_real<>(mn[0],mx[0]));
 	static UniRandGen rndY(randGen,boost::uniform_real<>(mn[1],mx[1]));
@@ -469,7 +470,7 @@
 			// check against bounding spheres of other clumps, and only check individual spheres if there is overlap
 			if(!periodic){
 				// check overlap with box margins first
-				if((pos+rad*Vector3r::Ones()).cwise().max(mx)!=mx || (pos-rad*Vector3r::Ones()).cwise().min(mn)!=mn){ FOREACH(const Sph& s, C.pack) if((s.c+s.r*Vector3r::Ones()).cwise().max(mx)!=mx || (s.c-s.r*Vector3r::Ones()).cwise().min(mn)!=mn) goto overlap; }
+				if((pos+rad*Vector3r::Ones()).cwiseMax(mx)!=mx || (pos-rad*Vector3r::Ones()).cwiseMin(mn)!=mn){ FOREACH(const Sph& s, C.pack) if((s.c+s.r*Vector3r::Ones()).cwiseMax(mx)!=mx || (s.c-s.r*Vector3r::Ones()).cwiseMin(mn)!=mn) goto overlap; }
 				// check overlaps with bounding spheres of other clumps
 				FOREACH(const ClumpInfo& cInfo, clumpInfos){
 					bool detailedCheck=false;

=== modified file 'pkg/dem/SpherePack.hpp'
--- pkg/dem/SpherePack.hpp	2011-11-02 15:09:47 +0000
+++ pkg/dem/SpherePack.hpp	2013-03-07 18:28:01 +0000
@@ -5,10 +5,12 @@
 #include<vector>
 #include<string>	
 #include<limits>
+#include<iostream>
 using namespace std; // sorry
 
 #include<boost/python.hpp>
-#include<yade/extra/boost_python_len.hpp>
+#include<boost/python/object.hpp>
+#include<boost/version.hpp>
 using namespace boost;
 
 #include<boost/foreach.hpp>
@@ -79,7 +81,7 @@
 
 	// generate packing of clumps, selected with equal probability
 	// periodic boundary is supported
-	long makeClumpCloud(const Vector3r& mn, const Vector3r& mx, const vector<shared_ptr<SpherePack> >& clumps, bool periodic=false, int num=-1);
+	long makeClumpCloud(const Vector3r& mn, const Vector3r& mx, const vector<shared_ptr<SpherePack> >& clumps, bool periodic=false, int num=-1, int seed=0);
 
 	// periodic repetition
 	void cellRepeat(Vector3i count);
@@ -90,7 +92,11 @@
 	python::tuple aabb_py() const { Vector3r mn,mx; aabb(mn,mx); return python::make_tuple(mn,mx); }
 	void aabb(Vector3r& mn, Vector3r& mx) const {
 		Real inf=std::numeric_limits<Real>::infinity(); mn=Vector3r(inf,inf,inf); mx=Vector3r(-inf,-inf,-inf);
-		FOREACH(const Sph& s, pack){ Vector3r r(s.r,s.r,s.r); mn=mn.cwise().min(s.c-r); mx=mx.cwise().max(s.c+r);}
+		FOREACH(const Sph& s, pack){ 
+      Vector3r r(s.r,s.r,s.r); 
+      mn=mn.cwiseMin(s.c-r); 
+      mx=mx.cwiseMax(s.c+r);
+    }
 	}
 	Vector3r midPt() const {Vector3r mn,mx; aabb(mn,mx); return .5*(mn+mx);}
 	Real relDensity() const {
@@ -106,11 +112,17 @@
 	// transformations
 	void translate(const Vector3r& shift){ FOREACH(Sph& s, pack) s.c+=shift; }
 	void rotate(const Vector3r& axis, Real angle){
-		if(cellSize!=Vector3r::Zero()) { LOG_WARN("Periodicity reset when rotating periodic packing (non-zero cellSize="<<cellSize<<")"); cellSize=Vector3r::Zero(); }
+		if(cellSize!=Vector3r::Zero()) { 
+      LOG_WARN("Periodicity reset when rotating periodic packing (non-zero cellSize="<<cellSize<<")"); 
+      cellSize=Vector3r::Zero(); 
+    }
 		Vector3r mid=midPt(); Quaternionr q(AngleAxisr(angle,axis)); FOREACH(Sph& s, pack) s.c=q*(s.c-mid)+mid;
 	}
 	void rotateAroundOrigin(const Quaternionr& rot){
-		if(cellSize!=Vector3r::Zero()){ LOG_WARN("Periodicity reset when rotating periodic packing (non-zero cellSize="<<cellSize<<")"); cellSize=Vector3r::Zero(); }
+		if(cellSize!=Vector3r::Zero()){ 
+      LOG_WARN("Periodicity reset when rotating periodic packing (non-zero cellSize="<<cellSize<<")"); 
+      cellSize=Vector3r::Zero(); 
+    }
 		FOREACH(Sph& s, pack) s.c=rot*s.c;
 	}
 	void scale(Real scale){ Vector3r mid=midPt(); cellSize*=scale; FOREACH(Sph& s, pack) {s.c=scale*(s.c-mid)+mid; s.r*=abs(scale); } }

=== modified file 'pkg/dem/TesselationWrapper.cpp'
--- pkg/dem/TesselationWrapper.cpp	2012-02-14 16:58:21 +0000
+++ pkg/dem/TesselationWrapper.cpp	2013-03-05 19:00:17 +0000
@@ -10,7 +10,8 @@
 
 #include<yade/lib/pyutil/numpy.hpp>
 #include<boost/python.hpp>
-#include<yade/extra/boost_python_len.hpp>
+#include<boost/python/object.hpp>
+#include<boost/version.hpp>
 #include<yade/pkg/dem/Shop.hpp>
 #include"TesselationWrapper.hpp"
 #include<yade/lib/triangulation/Timer.h>

=== modified file 'pkg/dem/TesselationWrapper.hpp'
--- pkg/dem/TesselationWrapper.hpp	2012-09-08 01:19:45 +0000
+++ pkg/dem/TesselationWrapper.hpp	2013-03-05 19:00:17 +0000
@@ -13,7 +13,8 @@
 #include<yade/core/Scene.hpp>
 #include<yade/lib/triangulation/Tesselation.h>
 #include<boost/python.hpp>
-#include<yade/extra/boost_python_len.hpp>
+#include<boost/python/object.hpp>
+#include<boost/version.hpp>
 #include<yade/pkg/dem/MicroMacroAnalyser.hpp>
 
 /*! \class TesselationWrapper

=== modified file 'pkg/dem/ThreeDTriaxialEngine.cpp'
--- pkg/dem/ThreeDTriaxialEngine.cpp	2012-02-09 17:37:02 +0000
+++ pkg/dem/ThreeDTriaxialEngine.cpp	2013-02-26 19:28:47 +0000
@@ -30,7 +30,8 @@
 
 void ThreeDTriaxialEngine::action()
 {
-
+	static int warn = 0;
+	if (!warn++) LOG_WARN ("This engine is deprecated, please switch to TriaxialStressController if you expect long term support.")
 	if ( firstRun )
 	{
 		LOG_INFO ( "First run, will initialize!" );
@@ -59,7 +60,7 @@
 
 		//internalCompaction=false;  //is needed to avoid a control for internal compaction by the TriaxialStressController engine
 
-		isAxisymetric=false; //is needed to avoid a stress control according the parameter sigma_iso (but according to sigma1, sigma2 and sigma3)
+// 		isAxisymetric=false; //is needed to avoid a stress control according the parameter sigma_iso (but according to sigma1, sigma2 and sigma3)
 
 		firstRun=false;
 

=== modified file 'pkg/dem/TriaxialCompressionEngine.cpp'
--- pkg/dem/TriaxialCompressionEngine.cpp	2012-11-13 13:10:00 +0000
+++ pkg/dem/TriaxialCompressionEngine.cpp	2013-03-06 20:39:22 +0000
@@ -106,6 +106,7 @@
 
 void TriaxialCompressionEngine::action()
 {
+	if (!warn++) LOG_WARN ("This engine is deprecated, please switch to TriaxialStressController if you expect long term support.")
 	// here, we make sure to get consistent parameters, in case someone fiddled with the scene .xml manually
 	if ( firstRun )
 	{
@@ -139,6 +140,12 @@
 		}
 		saveSimulation = false;
 	}
+	if (isAxisymetric || internalCompaction){
+		if (stressMask & 1) goal1=sigma_iso;
+		if (stressMask & 2) goal2=sigma_iso;
+		if (stressMask & 3) goal3=sigma_iso;
+	}
+	
 	TriaxialStressController::action();
 	if ( currentState==STATE_LIMBO && autoStopSimulation )
 	{

=== modified file 'pkg/dem/TriaxialCompressionEngine.hpp'
--- pkg/dem/TriaxialCompressionEngine.hpp	2012-09-19 16:27:15 +0000
+++ pkg/dem/TriaxialCompressionEngine.hpp	2013-03-06 20:39:22 +0000
@@ -87,6 +87,7 @@
 		"Transition from COMPACTION to UNLOADING is done automatically if autoUnload==true;\n\n Transition from (UNLOADING to LOADING) or from (COMPACTION to LOADING: if UNLOADING is skipped) is done automatically if autoCompressionActivation=true; Both autoUnload and autoCompressionActivation are true by default.\n\n"
 		"\n\n.. note::\n\t Most of the algorithms used have been developed initialy for simulations reported in [Chareyre2002a]_ and [Chareyre2005]_. They have been ported to Yade in a second step and used in e.g. [Kozicki2008]_,[Scholtes2009b]_,[Jerier2010b]."
 		,
+		((int, warn, 0,,"counter used for sending a deprecation warning once"))
 		((Real,strainRate,0,,"target strain rate (./s)"))
 		((Real,currentStrainRate,0,,"current strain rate - converging to :yref:`TriaxialCompressionEngine::strainRate` (./s)"))
 		((Real,UnbalancedForce,1,,"mean resultant forces divided by mean contact force"))
@@ -109,6 +110,8 @@
 		((Real,fixedPoroCompaction,false,,"A special type of compaction with imposed final porosity :yref:`TriaxialCompressionEngine::fixedPorosity` (WARNING : can give unrealistic results!)"))
 		((Real,fixedPorosity,0,,"Value of porosity chosen by the user"))
 		((Real,maxStress,0,,"Max value of stress during the simulation (for post-processing)"))
+		((Real,sigma_iso,0,,"prescribed confining stress (see :yref:TriaxialCompressionEngine::isAxisymetric`)"))
+		((bool,isAxisymetric,false,,"if true, sigma_iso is assigned to sigma1, 2 and 3 (applies at each iteration and overrides user-set values of s1,2,3)"))
 		,
 		translationAxisx=Vector3r(1,0,0);
 		translationAxisz=Vector3r(0,0,1);
@@ -121,6 +124,7 @@
 		previousSigmaIso=sigma_iso;
 		boxVolume=0;
 		saveSimulation=false;
+		isAxisymetric=true;
 		,
 	 	.def("setContactProperties",&TriaxialCompressionEngine::setContactProperties,"Assign a new friction angle (degrees) to dynamic bodies and relative interactions")
 		)

=== modified file 'pkg/dem/TriaxialStateRecorder.cpp'
--- pkg/dem/TriaxialStateRecorder.cpp	2011-10-21 17:43:08 +0000
+++ pkg/dem/TriaxialStateRecorder.cpp	2013-02-04 18:23:35 +0000
@@ -31,13 +31,13 @@
 		vector<shared_ptr<Engine> >::iterator itFirst = scene->engines.begin();
 		vector<shared_ptr<Engine> >::iterator itLast = scene->engines.end();
 		for ( ;itFirst!=itLast; ++itFirst ){
-			if ( ( *itFirst )->getClassName() == "TriaxialCompressionEngine" || ( *itFirst )->getClassName() == "ThreeDTriaxialEngine" ){
+			if ( ( *itFirst )->getClassName() == "TriaxialCompressionEngine" || ( *itFirst )->getClassName() == "ThreeDTriaxialEngine" || ( *itFirst )->getClassName() == "TriaxialStressController"){
 				LOG_DEBUG ( "stress controller engine found" );
 				triaxialStressController =  YADE_PTR_CAST<TriaxialStressController> ( *itFirst );
 				//triaxialCompressionEngine = shared_ptr<TriaxialCompressionEngine> (static_cast<TriaxialCompressionEngine*> ( (*itFirst).get()));
 			}
 		}
-		if ( !triaxialStressController ) LOG_DEBUG ( "stress controller engine NOT found" );
+		if ( !triaxialStressController ) LOG_ERROR ( "stress controller engine NOT found" );
 	}
 	if ( ! ( scene->iter % triaxialStressController->computeStressStrainInterval == 0 ) )
 		triaxialStressController->computeStressStrain ();

=== modified file 'pkg/dem/TriaxialStressController.cpp'
--- pkg/dem/TriaxialStressController.cpp	2011-04-22 09:04:48 +0000
+++ pkg/dem/TriaxialStressController.cpp	2013-04-09 11:46:11 +0000
@@ -61,7 +61,7 @@
 	   }
 	   else translation = wall_max_vel * Mathr::Sign(translation)*scene->dt;
 	}
-	previousTranslation[wall] = (1-wallDamping)*translation*normal[wall] + 0.8*previousTranslation[wall];// formula for "steady-flow" evolution with fluctuations
+	previousTranslation[wall] = (1-stressDamping)*translation*normal[wall] + 0.8*previousTranslation[wall];// formula for "steady-flow" evolution with fluctuations
 	//Don't update position since Newton is doing that starting from bzr2612
 // 	p->se3.position += previousTranslation[wall];
 	externalWork += previousTranslation[wall].dot(getForce(scene,wall_id[wall]));
@@ -107,17 +107,11 @@
 				spheresVolume += 1.3333333*Mathr::PI*pow ( sphere->radius, 3 );
 			}
 		}
-		max_vel1=3 * width /(height+width+depth)*max_vel;
-		max_vel2=3 * height /(height+width+depth)*max_vel;
-		max_vel3 =3 * depth /(height+width+depth)*max_vel;
 		first = false;
 	}
-
-	// NOT JUST at the first run, since sigma_iso may be changed
-	// if the TriaxialCompressionEngine is used, sigma_iso is attributed to sigma1, sigma2 and sigma3
-	if (isAxisymetric){
-		sigma1=sigma2=sigma3=sigma_iso;
-	}
+	max_vel1=3 * width /(height+width+depth)*max_vel;
+	max_vel2=3 * height /(height+width+depth)*max_vel;
+	max_vel3 =3 * depth /(height+width+depth)*max_vel;
 
 	porosity = ( boxVolume - spheresVolume ) /boxVolume;
 	position_top = p_top->se3.position.y();
@@ -137,34 +131,48 @@
 		computeStressStrain();
 
 	if (!internalCompaction) {
-		Vector3r wallForce (0, sigma2*width*depth, 0);
-		if (wall_bottom_activated) controlExternalStress(wall_bottom, -wallForce, p_bottom, max_vel2);
-		else p_bottom->vel=Vector3r::Zero();
-		if (wall_top_activated) controlExternalStress(wall_top, wallForce, p_top, max_vel2);
-		else p_top->vel=Vector3r::Zero();
-		wallForce = Vector3r(sigma1*height*depth, 0, 0);
-		if (wall_left_activated) controlExternalStress(wall_left, -wallForce, p_left, max_vel1);
-		else p_left->vel=Vector3r::Zero();
-		if (wall_right_activated) controlExternalStress(wall_right, wallForce, p_right, max_vel1);
-		else p_right->vel=Vector3r::Zero();
+		Vector3r wallForce (0, goal2*width*depth, 0);
+		if (wall_bottom_activated) {
+			if (stressMask & 2)  controlExternalStress(wall_bottom, -wallForce, p_bottom, max_vel2);
+			else p_bottom->vel[1] += (-normal[wall_bottom][1]*0.5*goal2*height -p_bottom->vel[1])*(1-strainDamping);
+		} else p_bottom->vel=Vector3r::Zero();
+		if (wall_top_activated) {
+			if (stressMask & 2)  controlExternalStress(wall_top, wallForce, p_top, max_vel2);
+			else p_top->vel[1] += (-normal[wall_top][1]*0.5*goal2*height -p_top->vel[1])*(1-strainDamping);
+		} else p_top->vel=Vector3r::Zero();
+		
+		wallForce = Vector3r(goal1*height*depth, 0, 0);
+		if (wall_left_activated) {
+			if (stressMask & 1) controlExternalStress(wall_left, -wallForce, p_left, max_vel1);
+			else p_left->vel[0] += (-normal[wall_left][0]*0.5*goal1*width -p_left->vel[0])*(1-strainDamping);
+		} else p_left->vel=Vector3r::Zero();
+		if (wall_right_activated) {
+			if (stressMask & 1) controlExternalStress(wall_right, wallForce, p_right, max_vel1);
+			else p_right->vel[0] += (-normal[wall_right][0]*0.5*goal1*width -p_right->vel[0])*(1-strainDamping);
+		} else p_right->vel=Vector3r::Zero();
 
-		wallForce = Vector3r(0, 0, sigma3*height*width);
-		if (wall_back_activated) controlExternalStress(wall_back, -wallForce, p_back, max_vel3);
-		else p_back->vel=Vector3r::Zero();
-		if (wall_front_activated) controlExternalStress(wall_front, wallForce, p_front, max_vel3);
-		else p_front->vel=Vector3r::Zero();
+		wallForce = Vector3r(0, 0, goal3*height*width);
+		if (wall_back_activated) {
+			if (stressMask & 4) controlExternalStress(wall_back, -wallForce, p_back, max_vel3);
+			else p_back->vel[2] += (-normal[wall_back][2]*0.5*goal3*depth -p_back->vel[2])*(1-strainDamping);
+		} else p_back->vel=Vector3r::Zero();
+		if (wall_front_activated) {
+			if (stressMask & 4) controlExternalStress(wall_front, wallForce, p_front, max_vel3);
+			else p_front->vel[2] += (-normal[wall_front][2]*0.5*goal3*depth -p_front->vel[2])*(1-strainDamping);
+		} else p_front->vel=Vector3r::Zero();
 	}
 	else //if internal compaction
 	{
 		p_bottom->vel=Vector3r::Zero(); p_top->vel=Vector3r::Zero(); p_left->vel=Vector3r::Zero(); p_right->vel=Vector3r::Zero(); p_back->vel=Vector3r::Zero(); p_front->vel=Vector3r::Zero();
 		if (isARadiusControlIteration) {
-			//Real s = computeStressStrain(scene);
-			if (sigma_iso<=meanStress) maxMultiplier = finalMaxMultiplier;
+			Real sigma_iso_ = bool(stressMask & 1)*goal1 +  bool(stressMask & 2)*goal2 +  bool(stressMask & 4)*goal3;
+			sigma_iso_ /=  bool(stressMask & 1) +  bool(stressMask & 2) +  bool(stressMask & 4);
+			if (sigma_iso_<=meanStress) maxMultiplier = finalMaxMultiplier;
 			if (meanStress==0) previousMultiplier = maxMultiplier;
 			else {
 				//     		previousMultiplier = 1+0.7*(sigma_iso-s)*(previousMultiplier-1.f)/(s-previousStress); // = (Dsigma/apparentModulus)*0.7
 				//     		previousMultiplier = std::max(2-maxMultiplier, std::min(previousMultiplier, maxMultiplier));
-				previousMultiplier = 1.+(sigma_iso-meanStress)/sigma_iso*(maxMultiplier-1.); // = (Dsigma/apparentModulus)*0.7
+				previousMultiplier = 1.+(sigma_iso_-meanStress)/sigma_iso_*(maxMultiplier-1.); // = (Dsigma/apparentModulus)*0.7
 			}
 			previousStress = meanStress;
 			//Real apparentModulus = (s-previousStress)/(previousMultiplier-1.f);

=== modified file 'pkg/dem/TriaxialStressController.hpp'
--- pkg/dem/TriaxialStressController.hpp	2011-10-06 14:58:10 +0000
+++ pkg/dem/TriaxialStressController.hpp	2013-02-07 18:12:42 +0000
@@ -73,14 +73,15 @@
 		///! Getter for stress in python
 		Vector3r getStress(int boundId);
 
-		YADE_CLASS_BASE_DOC_ATTRS_INIT_CTOR_PY(TriaxialStressController,BoundaryController,
-		"An engine maintaining constant stresses on some boundaries of a parallepipedic packing. See also :yref:`TriaxialCompressionEngine`"
+		YADE_CLASS_BASE_DOC_ATTRS_DEPREC_INIT_CTOR_PY(TriaxialStressController,BoundaryController,
+		"An engine maintaining constant stresses or constant strain rates on some boundaries of a parallepipedic packing. The stress/strain control is defined for each axis using :yref:`TriaxialStressController::stressMask` (a bitMask) and target values are defined by goal1,goal2, and goal3. sigmaIso has to be defined during growing phases."
 		"\n\n.. note::\n\t The algorithms used have been developed initialy for simulations reported in [Chareyre2002a]_ and [Chareyre2005]_. They have been ported to Yade in a second step and used in e.g. [Kozicki2008]_,[Scholtes2009b]_,[Jerier2010b]."
 		,
    		((unsigned int,stiffnessUpdateInterval,10,,"target strain rate (./s)"))
    		((unsigned int,radiusControlInterval,10,,""))
 		((unsigned int,computeStressStrainInterval,10,,""))
-		((Real,wallDamping,0.25,,"wallDamping coefficient - wallDamping=0 implies a (theoretical) perfect control, wallDamping=1 means no movement"))
+		((Real,stressDamping,0.25,,"wall damping coefficient for the stress control - wallDamping=0 implies a (theoretical) perfect control, wallDamping=1 means no movement"))
+		((Real,strainDamping,0.99,,"coefficient used for smoother transitions in the strain rate. The rate reaches the target value like $d^n$ reaches 0, where $d$ is the damping coefficient and $n$ is the number of steps"))
 		((Real,thickness,-1,,"thickness of boxes (needed by some functions)"))
 		((int,wall_bottom_id,2,,"id of boundary ; coordinate 1- (default value is ok if aabbWalls are appended BEFORE spheres.)"))
 		((int,wall_top_id,3,,"id of boundary ; coordinate 1+ (default value is ok if aabbWalls are appended BEFORE spheres.)"))
@@ -88,33 +89,39 @@
 		((int,wall_right_id,1,,"id of boundary ; coordinate 0+ (default value is ok if aabbWalls are appended BEFORE spheres.)"))
 		((int,wall_front_id,5,,"id of boundary ; coordinate 2+ (default value is ok if aabbWalls are appended BEFORE spheres.)"))
 		((int,wall_back_id,4,,"id of boundary ; coordinate 2- (default value is ok if aabbWalls are appended BEFORE spheres.)"))
-		((bool,wall_bottom_activated,true,,"if true, the engine is keeping stress constant on this boundary."))
-		((bool,wall_top_activated,true,,"if true, the engine is keeping stress constant on this boundary."))
-		((bool,wall_left_activated,true,,"if true, the engine is keeping stress constant on this boundary."))
-		((bool,wall_right_activated,true,,"if true, the engine is keeping stress constant on this boundary."))
-		((bool,wall_front_activated,true,,"if true, the engine is keeping stress constant on this boundary."))
-		((bool,wall_back_activated,true,,"if true, the engine is keeping stress constant on this boundary."))
+		((bool,wall_bottom_activated,true,,"if true, this wall moves according to the target value (stress or strain rate)."))
+		((bool,wall_top_activated,true,,"if true, this wall moves according to the target value (stress or strain rate)."))
+		((bool,wall_left_activated,true,,"if true, this wall moves according to the target value (stress or strain rate)."))
+		((bool,wall_right_activated,true,,"if true, this wall moves according to the target value (stress or strain rate)."))
+		((bool,wall_front_activated,true,,"if true, this wall moves according to the target value (stress or strain rate)."))
+		((bool,wall_back_activated,true,,"if true, this wall moves according to the target value (stress or strain rate)."))
 		((Real,height,0,Attr::readonly,"size of the box (1-axis) |yupdate|"))
 		((Real,width,0,Attr::readonly,"size of the box (0-axis) |yupdate|"))
 		((Real,depth,0,Attr::readonly,"size of the box (2-axis) |yupdate|"))
 		((Real,height0,0,Attr::readonly,"Reference size for strain definition. See :yref:`TriaxialStressController::height`"))
 		((Real,width0,0,Attr::readonly,"Reference size for strain definition. See :yref:`TriaxialStressController::width`"))
 		((Real,depth0,0,Attr::readonly,"Reference size for strain definition. See :yref:`TriaxialStressController::depth`"))
-		((Real,sigma_iso,0,,"prescribed confining stress (see :yref:`TriaxialStressController::isAxisymetric`)"))
-		((Real,sigma1,0,,"prescribed stress on axis 1 (see :yref:`TriaxialStressController::isAxisymetric`)"))
-		((Real,sigma2,0,,"prescribed stress on axis 2 (see :yref:`TriaxialStressController::isAxisymetric`)"))
-		((Real,sigma3,0,,"prescribed stress on axis 3 (see :yref:`TriaxialStressController::isAxisymetric`)"))
-		((bool,isAxisymetric,true,,"if true, sigma_iso is assigned to sigma1, 2 and 3 (applies at each iteration and overrides user-set values of s1,2,3)"))
+		
+		((Real,goal1,0,,"prescribed stress/strain rate on axis 1, as defined by :yref:`TriaxialStressController::stressMask` (see also :yref:`TriaxialStressController::isAxisymetric`)"))
+		((Real,goal2,0,,"prescribed stress/strain rate on axis 2, as defined by :yref:`TriaxialStressController::stressMask` (see also :yref:`TriaxialStressController::isAxisymetric`)"))
+		((Real,goal3,0,,"prescribed stress/strain rate on axis 3, as defined by :yref:`TriaxialStressController::stressMask` (see also :yref:`TriaxialStressController::isAxisymetric`)"))
+		((unsigned int,stressMask,7,,"Bitmask determining if the components of :yref:`TriaxialStressController::goal` are stress (1) or strain (0). 0 for none, 7 for all, 1 for sigma1, etc."))
 		((Real,maxMultiplier,1.001,,"max multiplier of diameters during internal compaction (initial fast increase - :yref:`TriaxialStressController::finalMaxMultiplier` is used in a second stage)"))
 		((Real,finalMaxMultiplier,1.00001,,"max multiplier of diameters during internal compaction (secondary precise adjustment - :yref:`TriaxialStressController::maxMultiplier` is used in the initial stage)"))
-		((Real,max_vel,0.001,,"Maximum allowed walls velocity [m/s]. This value superseeds the one assigned by the stress controller if the later is higher. max_vel can be set to infinity in many cases, but sometimes helps stabilizing packings. Based on this value, different maxima are computed for each axis based on the dimensions of the sample, so that if each boundary moves at its maximum velocity, the strain rate will be isotropic (see e.g. :yref:`TriaxialStressController::max_vel1`)."))
+		((Real,max_vel,1,,"Maximum allowed walls velocity [m/s]. This value superseeds the one assigned by the stress controller if the later is higher. max_vel can be set to infinity in many cases, but sometimes helps stabilizing packings. Based on this value, different maxima are computed for each axis based on the dimensions of the sample, so that if each boundary moves at its maximum velocity, the strain rate will be isotropic (see e.g. :yref:`TriaxialStressController::max_vel1`)."))
 		((Real,previousStress,0,Attr::readonly,"|yupdate|"))
 		((Real,previousMultiplier,1,Attr::readonly,"|yupdate|"))
 		((bool,internalCompaction,true,,"Switch between 'external' (walls) and 'internal' (growth of particles) compaction."))
 		((Real,meanStress,0,Attr::readonly,"Mean stress in the packing. |yupdate|"))
 		((Real,volumetricStrain,0,Attr::readonly,"Volumetric strain (see :yref:`TriaxialStressController::strain`).|yupdate|"))
 		((Real,externalWork,0,Attr::readonly,"Energy provided by boundaries.|yupdate|"))
- 		,
+		,
+		/* deprecated */
+		((sigma1,goal1,"renamed 'goal1', it can now also be a strain depending on stressMask"))
+		((sigma2,goal2,"renamed 'goal2', it can now also be a strain depending on stressMask"))
+		((sigma3,goal3,"renamed 'goal3', it can now also be a strain depending on stressMask"))
+		((wallDamping,stressDamping,"renamed to make the distinction with strain damping"))
+		,
 		/* extra initializers */
 		,
    		/* constructor */

=== modified file 'pkg/dem/TriaxialTest.cpp'
--- pkg/dem/TriaxialTest.cpp	2012-06-28 19:34:29 +0000
+++ pkg/dem/TriaxialTest.cpp	2013-03-06 20:39:22 +0000
@@ -274,6 +274,8 @@
 	// moving walls to regulate the stress applied + compress when the packing is dense an stable
 	//cerr << "triaxialcompressionEngine = shared_ptr<TriaxialCompressionEngine> (new TriaxialCompressionEngine);" << std::endl;
 	triaxialcompressionEngine = shared_ptr<TriaxialCompressionEngine> (new TriaxialCompressionEngine);
+	//This prevent the deprecation warning. In fact this preprocessor in itself is becoming deprecated
+	triaxialcompressionEngine->warn = 1;
 	triaxialcompressionEngine-> stiffnessUpdateInterval = wallStiffnessUpdateInterval;// = stiffness update interval
 	triaxialcompressionEngine-> radiusControlInterval = radiusControlInterval;// = stiffness update interval
 	triaxialcompressionEngine-> sigmaIsoCompaction = sigmaIsoCompaction;

=== modified file 'pkg/dem/VTKRecorder.cpp'
--- pkg/dem/VTKRecorder.cpp	2012-09-26 18:01:26 +0000
+++ pkg/dem/VTKRecorder.cpp	2013-03-07 18:28:01 +0000
@@ -353,7 +353,7 @@
 					cpmDamage->InsertNextValue(YADE_PTR_CAST<CpmState>(b->state)->normDmg);
 					const Matrix3r& ss=YADE_PTR_CAST<CpmState>(b->state)->stress;
 					//float s[3]={ss[0],ss[1],ss[2]};
-					float s[9]={ (float) ss[0,0], (float) ss[0,1], (float) ss[0,2], (float) ss[1,0], (float) ss[1,1], (float) ss[1,2], (float) ss[2,0], (float) ss[2,1], (float) ss[2,2]};
+					float s[9]={ (float) ss(0,0), (float) ss(0,1), (float) ss(0,2), (float) ss(1,0), (float) ss(1,1), (float) ss(1,2), (float) ss(2,0), (float) ss(2,1), (float) ss(2,2)};
 					cpmStress->InsertNextTupleValue(s);
 				}
 				if (recActive[REC_RPM]){

=== modified file 'pkg/dem/VTKRecorder.hpp'
--- pkg/dem/VTKRecorder.hpp	2012-09-08 01:19:45 +0000
+++ pkg/dem/VTKRecorder.hpp	2013-04-24 19:49:00 +0000
@@ -23,7 +23,7 @@
 			((bool,multiblock,false,,"Use multi-block (``.vtm``) files to store data, rather than separate ``.vtu`` files."))
 		#endif
 		((string,fileName,"",,"Base file name; it will be appended with {spheres,intrs,facets}-243100.vtu (unless *multiblock* is ``True``) depending on active recorders and step number (243100 in this case). It can contain slashes, but the directory must exist already."))
-		((vector<string>,recorders,vector<string>(1,string("all")),,"List of active recorders (as strings). ``all`` (the default value) enables all base and generic recorders.\n\n.. admonition:: Base recorders\n\n\tBase recorders save the geometry (unstructured grids) on which other data is defined. They are implicitly activated by many of the other recorders. Each of them creates a new file (or a block, if :yref:`multiblock <VTKRecorder.multiblock>` is set).\n\n\t``spheres``\n\t\tSaves positions and radii (``radii``) of :yref:`spherical<Sphere>` particles.\n\t``facets``\n\t\tSave :yref:`facets<Facet>` positions (vertices).\n\t``boxes``\n\t\tSave :yref:`boxes<Box>` positions (edges).\n\t``intr``\n\t\tStore interactions as lines between nodes at respective particles positions. Additionally stores magnitude of normal (``forceN``) and shear (``absForceT``) forces on interactions (the :yref:`geom<Interaction.geom> must be of type :yref:`NormShearPhys`). \n\n.. admonition:: Generic recorders\n\n\tGeneric recorders do not depend on specific model being used and save commonly useful data.\n\n\t``id``\n\t\tSaves id's (field ``id``) of spheres; active only if ``spheres`` is active.\n\t``mass``\n\t\tSaves masses (field ``mass``) of spheres; active only if ``spheres`` is active.\n\t``clumpId``\n\t\tSaves id's of clumps to which each sphere belongs (field ``clumpId``); active only if ``spheres`` is active.\n\t``colors``\n\t\tSaves colors of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>` (field ``color``); only active if ``spheres`` or ``facets`` are activated.\n\t``mask``\n\t\tSaves groupMasks of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>` (field ``mask``); only active if ``spheres`` or ``facets`` are activated.\n\t``materialId``\n\t\tSaves materialID of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>`; only active if ``spheres`` or ``facets`` are activated.\n\t``velocity``\n\t\tSaves linear and angular velocities of spherical particles as Vector3 and length(fields ``linVelVec``, ``linVelLen`` and ``angVelVec``, ``angVelLen`` respectively``); only effective with ``spheres``.\n\t``stress``\n\t\tSaves stresses of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>`  as Vector3 and length; only active if ``spheres`` or ``facets`` are activated.\n\n.. admonition:: Specific recorders\n\n\tThe following should only be activated in appropriate cases, otherwise crashes can occur due to violation of type presuppositions.\n\n\t``cpm``\n\t\tSaves data pertaining to the :yref:`concrete model<Law2_Dem3DofGeom_CpmPhys_Cpm>`: ``cpmDamage`` (normalized residual strength averaged on particle), ``cpmStress`` (stress on particle); ``intr`` is activated automatically by ``cpm``\n\t``rpm``\n\t\tSaves data pertaining to the :yref:`rock particle model<Law2_Dem3DofGeom_RockPMPhys_Rpm>`: ``rpmSpecNum`` shows different pieces of separated stones, only ids. ``rpmSpecMass`` shows masses of separated stones.\n\t``wpm``\n\t\tSaves data pertaining to the :yref:`wire particle model<Law2_ScGeom_WirePhys_WirePM>`: ``wpmForceNFactor`` shows the loading factor for the wire, e.g. normal force divided by threshold normal force.\n\n"))
+		((vector<string>,recorders,vector<string>(1,string("all")),,"List of active recorders (as strings). ``all`` (the default value) enables all base and generic recorders.\n\n.. admonition:: Base recorders\n\n\tBase recorders save the geometry (unstructured grids) on which other data is defined. They are implicitly activated by many of the other recorders. Each of them creates a new file (or a block, if :yref:`multiblock <VTKRecorder.multiblock>` is set).\n\n\t``spheres``\n\t\tSaves positions and radii (``radii``) of :yref:`spherical<Sphere>` particles.\n\t``facets``\n\t\tSave :yref:`facets<Facet>` positions (vertices).\n\t``boxes``\n\t\tSave :yref:`boxes<Box>` positions (edges).\n\t``intr``\n\t\tStore interactions as lines between nodes at respective particles positions. Additionally stores magnitude of normal (``forceN``) and shear (``absForceT``) forces on interactions (the :yref:`geom<Interaction.geom> must be of type :yref:`NormShearPhys`). \n\n.. admonition:: Generic recorders\n\n\tGeneric recorders do not depend on specific model being used and save commonly useful data.\n\n\t``id``\n\t\tSaves id's (field ``id``) of spheres; active only if ``spheres`` is active.\n\t``mass``\n\t\tSaves masses (field ``mass``) of spheres; active only if ``spheres`` is active.\n\t``clumpId``\n\t\tSaves id's of clumps to which each sphere belongs (field ``clumpId``); active only if ``spheres`` is active.\n\t``colors``\n\t\tSaves colors of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>` (field ``color``); only active if ``spheres`` or ``facets`` are activated.\n\t``mask``\n\t\tSaves groupMasks of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>` (field ``mask``); only active if ``spheres`` or ``facets`` are activated.\n\t``materialId``\n\t\tSaves materialID of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>`; only active if ``spheres`` or ``facets`` are activated.\n\t``velocity``\n\t\tSaves linear and angular velocities of spherical particles as Vector3 and length(fields ``linVelVec``, ``linVelLen`` and ``angVelVec``, ``angVelLen`` respectively``); only effective with ``spheres``.\n\t``stress``\n\t\tSaves stresses of :yref:`spheres<Sphere>` and of :yref:`facets<Facet>`  as Vector3 and length; only active if ``spheres`` or ``facets`` are activated.\n\n.. admonition:: Specific recorders\n\n\tThe following should only be activated in appropriate cases, otherwise crashes can occur due to violation of type presuppositions.\n\n\t``cpm``\n\t\tSaves data pertaining to the :yref:`concrete model<Law2_ScGeom_CpmPhys_Cpm>`: ``cpmDamage`` (normalized residual strength averaged on particle), ``cpmStress`` (stress on particle); ``intr`` is activated automatically by ``cpm``\n\t``rpm``\n\t\tSaves data pertaining to the :yref:`rock particle model<Law2_Dem3DofGeom_RockPMPhys_Rpm>`: ``rpmSpecNum`` shows different pieces of separated stones, only ids. ``rpmSpecMass`` shows masses of separated stones.\n\t``wpm``\n\t\tSaves data pertaining to the :yref:`wire particle model<Law2_ScGeom_WirePhys_WirePM>`: ``wpmForceNFactor`` shows the loading factor for the wire, e.g. normal force divided by threshold normal force.\n\n"))
 		((int,mask,0,,"If mask defined, only bodies with corresponding groupMask will be exported. If 0, all bodies will be exported.")),
 		/*ctor*/
 		initRun=true;

=== removed directory 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders'
=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/algorithms.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/algorithms.hpp	2012-10-16 17:36:24 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/algorithms.hpp	1970-01-01 00:00:00 +0000
@@ -1,564 +0,0 @@
-// Header file algorithms.hpp
-//
-// Uniform interface layer for all containers.
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/ 9/11   rmg     File creation from suite_utils.hpp
-// 2003/10/28   rmg     Split container-specific versions into separate headers
-// 2006/10/25   Roman   Adding keys function to assoc_algorithms class
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: algorithms.hpp,v 1.1.2.15 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_ALGORITHMS_HPP
-#define BOOST_PYTHON_INDEXING_ALGORITHMS_HPP
-
-#include <indexing_suite/suite_utils.hpp>
-
-#include <boost/type_traits.hpp>
-#include <boost/python/errors.hpp>
-#include <indexing_suite/int_slice_helper.hpp>
-#include <indexing_suite/slice.hpp>
-#include <boost/mpl/if.hpp>
-#include <boost/limits.hpp>
-#include <algorithm>
-#include <functional>
-#include <stdexcept>
-#include <string>
-#include <set>
-
-namespace boost { namespace python { namespace indexing {
-  template<typename ContainerTraits, typename Ovr = detail::no_override>
-  class default_algorithms
-  {
-    typedef default_algorithms<ContainerTraits, Ovr> self_type;
-    typedef typename detail::maybe_override<self_type, Ovr>
-        ::type most_derived;
-
-  public:
-    typedef ContainerTraits container_traits;
-
-    // Import typedefs from the container_traits for convenience
-    typedef typename ContainerTraits::container   container;
-    typedef typename ContainerTraits::iterator    iterator;
-    typedef typename ContainerTraits::reference   reference;
-    typedef typename ContainerTraits::size_type   size_type;
-    typedef typename ContainerTraits::value_type  value_type;
-    typedef typename ContainerTraits::value_param value_param;
-    typedef typename ContainerTraits::index_param index_param;
-    typedef typename ContainerTraits::key_param   key_param;
-
-    // Defer selection of supported_methods to the ContainerTraits
-    // template argument. This makes sense because default_algorithms
-    // derives all of its other information from this argument, and
-    // can't decide which of the static member functions will
-    // instantiate successfully for the container. Obviously a
-    // custom-written Algorithms implementation could choose to
-    // provide the supported_methods directly.
-
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = ContainerTraits::supported_methods);
-
-    static size_type size       (container &);
-    static iterator  find       (container &, key_param);
-    static size_type get_index  (container &, key_param);
-    static size_type count      (container &, key_param);
-    static bool      contains   (container &, key_param);
-    static void      reverse    (container &);
-    static reference get        (container &, index_param);
-    static void      assign     (container &, index_param, value_param);
-    static void      insert     (container &, index_param, value_param);
-    static void      erase_one  (container &, index_param);
-    static void      erase_range(container &, index_param, index_param);
-    static void      push_back  (container &, value_param);
-    static void      sort       (container &);
-    //    static void      sort       (container &, PyObject *);
-
-    static iterator  begin      (container &c) { return c.begin(); }
-    static iterator  end        (container &c) { return c.end(); }
-
-    // Reasonable defaults for slice handling
-    typedef int_slice_helper<self_type, integer_slice> slice_helper;
-
-    static slice_helper make_slice_helper (container &c, slice const &);
-
-    // Default visit_container_class
-    template<typename PythonClass, typename Policy>
-    static void visit_container_class(
-        PythonClass &pyClass, Policy const &policy)
-    {
-      container_traits::visit_container_class (pyClass, policy);
-    }
-
-#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
-    // MSVC6 and 7.0 seem to complain about most_derived::bounds_check
-    // for an instantiation of list_algorithms.
-  public:
-#else
-  private:
-#endif
-    static size_type bounds_check(
-        container &, index_param, char const *msg,
-        bool one_past = false,
-        bool truncate = false);
-    // Throws std::out_of_range if necessary. If one_past is set, then
-    // indexes up to container.size() *inclusive* are allowed. If
-    // truncate is set, then out of bounds values are reset to the
-    // nearest in-bound value (and if none exists, throws an
-    // exception). If truncate is *not* set, then negative values index
-    // from the upper bound backwards and are bounds-checked.
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Base class for associative containers
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr = detail::no_override>
-  class assoc_algorithms
-    : public default_algorithms
-        <ContainerTraits,
-        BOOST_DEDUCED_TYPENAME detail::maybe_override
-            <assoc_algorithms<ContainerTraits, Ovr>, Ovr>
-          ::type>
-  {
-    typedef assoc_algorithms<ContainerTraits, Ovr> self_type;
-    typedef typename detail::maybe_override<self_type, Ovr>
-        ::type most_derived;
-    typedef default_algorithms<ContainerTraits, most_derived> Parent;
-
-  public:
-    typedef typename Parent::iterator iterator;
-    typedef typename Parent::size_type size_type;
-    typedef typename Parent::container container;
-    typedef typename Parent::reference reference;
-    typedef typename Parent::key_param key_param;
-    typedef typename Parent::value_param value_param;
-    typedef typename Parent::index_param index_param;
-
-    static reference get        (container &, index_param);
-
-    // Use member functions for the following (hiding base class versions)
-    static void      erase_one (container &, key_param);
-    static iterator  find      (container &, key_param);
-    static size_type count     (container &, key_param);
-    static bool      contains  (container &, key_param);
-
-    // Default visit_container_class
-    template<typename PythonClass, typename Policy>
-    static void visit_container_class( PythonClass &pyClass, Policy const &policy)
-    {
-      ContainerTraits::visit_container_class (pyClass, policy);
-    }
-
-
-  protected:
-    static iterator  find_or_throw (container &, index_param);
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Get the size of a container
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::size_type
-  default_algorithms<ContainerTraits, Ovr>::size (container &c)
-  {
-    return c.size();
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Range check an index and throw out_of_range if necessary
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::size_type
-  default_algorithms<ContainerTraits, Ovr>::bounds_check(
-      container &c,
-      index_param ix,
-      char const *msg,
-      bool one_past,
-      bool truncate)
-  {
-    size_type bound = most_derived::size(c) + (one_past ? 1 : 0);
-    size_type result;
-
-    if (truncate)
-      {
-        if (ix < 0)
-          {
-            result = 0;
-          }
-
-        else
-          {
-            result = ix;
-
-            if ((result >= bound) && (bound > 0))
-              {
-                result = bound - 1;
-              }
-          }
-      }
-
-    else if (ix < 0)
-      {
-        if (size_type(-ix) > bound)
-          {
-            throw std::out_of_range (msg);
-          }
-
-        result = bound + ix;
-      }
-
-    else
-      {
-        result = ix;
-      }
-
-    if (result >= bound)
-      {
-        throw std::out_of_range (msg);
-      }
-
-    return result;
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Find an element in a container (std algorithm version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::iterator
-  default_algorithms<ContainerTraits, Ovr>::find(
-      container &c, key_param key)
-  {
-    typedef typename container_traits::value_traits_type vtraits;
-    typedef typename vtraits::equal_to comparison;
-
-    return std::find_if(
-        most_derived::begin(c),
-        most_derived::end(c),
-        std::bind (comparison(), key));
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Find an element and return its index (std algorithm version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::size_type
-  default_algorithms<ContainerTraits, Ovr>::get_index(
-      container &c, key_param key)
-  {
-    iterator found (most_derived::find (c, key));
-
-    if (found == most_derived::end(c))
-      {
-        PyErr_SetString(
-            PyExc_ValueError, "get_index: element not found");
-
-        boost::python::throw_error_already_set ();
-      }
-
-    iterator start (most_derived::begin (c));
-    return std::distance (start, found);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Count occurances of an element in a container (std algorithm version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::size_type
-  default_algorithms<ContainerTraits, Ovr>::count(
-      container &c, key_param key)
-  {
-    typedef typename container_traits::value_traits_type vtraits;
-    typedef typename vtraits::equal_to comparison;
-
-    return std::count_if(
-        most_derived::begin(c),
-        most_derived::end(c),
-        std::bind (comparison(), key));
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Check whether a container contains the given element (std algo ver)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  bool
-  default_algorithms<ContainerTraits, Ovr>::contains(
-      container &c, key_param key)
-  {
-    return most_derived::find (c, key) != most_derived::end(c);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Index into a container (generic version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::reference
-  default_algorithms<ContainerTraits, Ovr>::get(
-      container &c, index_param ix)
-  {
-    return c[most_derived::bounds_check (c, ix, "get")];
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Assign a value at a particular index (generic version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  default_algorithms<ContainerTraits, Ovr>::assign(
-      container &c, index_param ix, value_param val)
-  {
-    c[most_derived::bounds_check (c, ix, "assign")] = val;
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Insert at end of a container (generic version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  default_algorithms<ContainerTraits, Ovr>::push_back(
-      container &c, value_param v)
-  {
-    c.push_back (v);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Insert at an index in the container (generic version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  default_algorithms<ContainerTraits, Ovr>::insert(
-      container &c, index_param i, value_param v)
-  {
-    iterator insert_pos (most_derived::begin(c));
-
-    // Index may range up to c.size() inclusive to allow inserting at end
-    std::advance(
-        insert_pos, most_derived::bounds_check (c, i, "insert", true, true));
-
-    c.insert (insert_pos, v);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Erase between given indexes in the container (generic version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  default_algorithms<ContainerTraits, Ovr>::erase_range(
-      container &c, index_param from, index_param to)
-  {
-    iterator start (most_derived::begin(c));
-    iterator finish (most_derived::begin(c));
-
-    // Start index must be properly in bounds
-    std::advance
-      (start, most_derived::bounds_check (c, from, "erase_range (from)"));
-
-    // End index is one-past-the-end, so may range up to c.size() inclusive
-    std::advance
-      (finish, most_derived::bounds_check (c, to, "erase_range (to)", true));
-
-    c.erase (start, finish);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Erase one element at the given index in the container (generic version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  default_algorithms<ContainerTraits, Ovr>::erase_one(
-      container &c, index_param ix)
-  {
-    iterator iter (most_derived::begin(c));
-    std::advance (iter, most_derived::bounds_check (c, ix, "erase_one"));
-    c.erase (iter);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Reverse the contents of a container (std algorithm version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void default_algorithms<ContainerTraits, Ovr>::reverse (container &c)
-  {
-    std::reverse (most_derived::begin(c), most_derived::end(c));
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Sort the contents of a container (std algorithm version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void default_algorithms<ContainerTraits, Ovr>::sort (container &c)
-  {
-    typedef typename container_traits::value_traits_type vtraits;
-    typedef typename vtraits::less comparison;
-    std::sort (most_derived::begin(c), most_derived::end(c), comparison());
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // slice_helper factory function (default version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME default_algorithms<ContainerTraits, Ovr>::slice_helper
-  default_algorithms<ContainerTraits, Ovr>
-  ::make_slice_helper (container &c, slice const &sl)
-  {
-    return slice_helper (c, integer_slice (sl, most_derived::size (c)));
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Index into a container (associative version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME assoc_algorithms<ContainerTraits, Ovr>::reference
-  assoc_algorithms<ContainerTraits, Ovr>::get (container &c, index_param ix)
-  {
-    return *most_derived::find_or_throw (c, ix);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Erase elements with the given key (associative version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  assoc_algorithms<ContainerTraits, Ovr>::erase_one(
-      container &c, key_param key)
-  {
-    if (c.erase (key) == 0)
-      {
-        PyErr_SetString(
-            PyExc_ValueError, "Container does not hold value to be erased");
-
-        boost::python::throw_error_already_set ();
-      }
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Find an element in an associative container
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME assoc_algorithms<ContainerTraits, Ovr>::iterator
-  assoc_algorithms<ContainerTraits, Ovr>
-  ::find (container &c, key_param key)
-  {
-    return c.find (key);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Find an element in an associative container
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  bool
-  assoc_algorithms<ContainerTraits, Ovr>::contains(
-      container &c, key_param key)
-  {
-    return most_derived::find (c, key) != most_derived::end(c);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Find an element in an associative container - throw an exception if
-  // not found
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME assoc_algorithms<ContainerTraits, Ovr>::iterator
-  assoc_algorithms<ContainerTraits, Ovr>::find_or_throw(
-      container &c, index_param ix)
-  {
-    iterator iter = most_derived::find (c, ix);
-
-    if (iter == most_derived::end(c))
-      {
-        PyErr_SetString(
-            PyExc_ValueError, "associative container: key not found");
-
-        boost::python::throw_error_already_set ();
-      }
-
-    return iter;
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Count occurances of an element in a container (associative version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME assoc_algorithms<ContainerTraits, Ovr>::size_type
-  assoc_algorithms<ContainerTraits, Ovr>::count(
-      container &c, key_param key)
-  {
-    return c.count (key);
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Some meta-information to select algorithms for const and
-  // non-const qualified containers. All algorithms_selector specializations
-  // include two publically accessible typedefs, called
-  // mutable_algorithms and const_algorithms.  This saves having to
-  // have separate partial specializations of algorithms for
-  // const and non-const containers. Client code should probably
-  // specialize algorithms directly.
-  /////////////////////////////////////////////////////////////////////////
-
-  namespace detail {
-    template<typename Container> class algorithms_selector
-# if defined(BOOST_MPL_MSVC_ETI_BUG)
-    {
-      // Bogus types to prevent compile errors due to ETI
-      typedef algorithms_selector<Container> mutable_algorithms;
-      typedef algorithms_selector<Container> const_algorithms;
-    }
-# endif
-    ;
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Algorithms selection for mutable containers
-  /////////////////////////////////////////////////////////////////////////
-
-  template<class Container>
-  struct algorithms
-    : public detail::algorithms_selector<Container>::mutable_algorithms
-  {
-  };
-
-# if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  /////////////////////////////////////////////////////////////////////////
-  // Algorithms selection for const-qualified containers
-  /////////////////////////////////////////////////////////////////////////
-
-  template<class Container>
-  struct algorithms<Container const>
-    : public detail::algorithms_selector<Container>::const_algorithms
-  {
-  };
-# endif
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_ALGORITHMS_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_proxy.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_proxy.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_proxy.hpp	1970-01-01 00:00:00 +0000
@@ -1,738 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file container_proxy.hpp
-//
-// A container-wrapper that provides Python-style reference semantics
-// for values stored in vector-like containers via element proxies.
-//
-// Class invariant:
-//   size() == m_proxies.size()
-//   for 0 <= i < size()
-//     m_proxies[i].get() != 0
-//     m_proxies[i]->owner() == this
-//     m_proxies[i]->index() == i
-//     m_proxies[i]->m_element_ptr.get() == 0
-//
-// History
-// =======
-// 2003/ 8/26   rmg     File creation
-// 2003/10/23   rmg     Change pointer container from map to sequence
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: container_proxy.hpp,v 1.1.2.28 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP
-#define BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP
-
-#include <indexing_suite/proxy_iterator.hpp>
-#include <indexing_suite/shared_proxy_impl.hpp>
-#include <indexing_suite/element_proxy.hpp>
-#include <indexing_suite/element_proxy_traits.hpp>
-#include <indexing_suite/workaround.hpp>
-#include <indexing_suite/methods.hpp>
-
-#include <vector>
-#include <cassert>
-#include <boost/shared_ptr.hpp>
-#include <boost/mpl/apply.hpp>
-#include <boost/iterator/iterator_traits.hpp>
-#include <indexing_suite/container_traits.hpp>
-#include <indexing_suite/container_suite.hpp>
-#include <indexing_suite/algorithms.hpp>
-
-namespace boost { namespace python { namespace indexing {
-
-  template<typename T> struct identity {
-    typedef T held_type;
-
-    static T &       get(T &       obj) { return obj; }
-    static T const & get(T const & obj) { return obj; }
-
-    static T    create ()                     { return T(); }
-    static T    copy   (T const &copy)        { return copy; }
-    static void assign (T &to, T const &from) { to = from; }
-    static void pre_destruction (T &)         { }
-    static void swap   (T &one, T &two)       { std::swap (one, two); }
-  };
-
-  template<typename P> struct deref {
-    typedef P held_type;
-
-    typedef typename boost::iterator_value<P>::type     value;
-
-    static value &       get (P &       ptr)  { return *ptr; }
-    static value const & get (P const & ptr)  { return *ptr; }
-
-    static P    create ()                     { return P(); }
-    static P    copy   (P const &copy)        { return copy; }
-    static void assign (P &to, P const &from) { to = from; }
-    static void pre_destruction (P &)         { }
-    static void swap   (P &one, P &two)       { std::swap (one, two); }
-  };
-
-  struct vector_generator {
-    // Generates vector type for any element type with default allocator
-    template<typename Element> struct apply {
-      typedef std::vector<Element> type;
-    };
-  };
-
-#if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
-  // Early template instantiation (ETI) workaround
-  namespace detail {
-    template<typename Container> struct msvc6_iterator {
-      typedef Container::iterator type;
-    };
-
-    template<> struct msvc6_iterator<int> {
-      typedef int *type;
-    };
-  }
-#endif
-
-  template<class Container,
-           class Holder = identity<Container>,
-           class Generator = vector_generator>
-  class container_proxy
-  {
-    typedef container_proxy<Container, Holder, Generator> self_type;
-    typedef typename Container::iterator raw_iterator;
-    typedef ::boost::detail::iterator_traits<raw_iterator> raw_iterator_traits;
-
-#if !defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
-    template<class C> friend class shared_proxy_impl;
-    template<class C, typename E, typename T, typename S, typename I>
-        friend class proxy_iterator;
-#endif
-
-  public:
-    typedef typename Holder::held_type held_type;
-
-    typedef typename Container::size_type size_type;
-    typedef typename Container::difference_type difference_type;
-
-    typedef shared_proxy_impl<self_type> shared_proxy;
-
-    typedef typename Container::value_type raw_value_type;
-
-    typedef element_proxy<self_type> value_type;
-    typedef value_type               reference;  // Already has ref. semantics
-
-    typedef const_element_proxy<self_type> const_value_type;
-    typedef const_value_type               const_reference; // Ref. semantics
-
-    typedef proxy_iterator <self_type, value_type, raw_iterator_traits,
-        size_type, raw_iterator> iterator;
-    typedef iterator const_iterator; // No const_iterator yet implemented
-
-  public:
-    // Constructors
-    template<typename Iter> container_proxy (Iter start, Iter finish)
-      // Define inline for MSVC6 compatibility
-      : m_held_obj (Holder::create()),
-      m_proxies ()
-    {
-      insert (begin(), start, finish);
-    }
-
-    container_proxy ();
-    explicit container_proxy (held_type const &h);
-
-    container_proxy (container_proxy const &);
-    container_proxy &operator= (container_proxy const &);
-    ~container_proxy ();
-
-    Container const &raw_container() const;   // OK to expose const reference
-
-    reference       at (size_type index);
-    const_reference at (size_type index) const;
-
-    reference       operator[] (size_type index)       { return at(index); }
-    const_reference operator[] (size_type index) const { return at(index); }
-
-    size_type size ()     const { return raw_container().size(); }
-    size_type capacity () const { return raw_container().capacity(); }
-    void reserve (size_type s);
-
-  public:
-    iterator begin() { return iterator (this, static_cast<size_type>(0)); }
-    iterator end() { return iterator (this, raw_container().size()); }
-
-    iterator erase (iterator);
-    iterator erase (iterator, iterator);
-    iterator insert (iterator, raw_value_type const &);
-
-    template<typename Iter> void insert (iterator iter, Iter from, Iter to)
-      // Define here for MSVC6 compatibility
-    {
-      // Forward insertion to the right overloaded version
-      typedef typename BOOST_ITERATOR_CATEGORY<Iter>::type category;
-      insert (iter, from, to, category());
-    }
-
-    void push_back (raw_value_type const &copy) { insert (end(), copy); }
-
-    value_type pop_back () {
-      value_type result = at (size() - 1);
-      erase (end() - 1);
-      return result;
-    }
-
-  public:
-    // These functions are useful only when client code has direct
-    // non-const acccess to the raw container (e.g. via an indirect
-    // holder supplied to our constructor). Any code that directly
-    // modifies the contents of the raw container (by replacing,
-    // inserting or erasing elements) must notify the container_proxy.
-
-    void detach_proxy (size_type index);
-    void detach_proxies (size_type from, size_type to);
-    // Call before overwriting element(s) in the raw container
-
-    void prepare_erase (size_type from, size_type to);
-    // Call before erasing elements directly from the raw container
-
-    void notify_insertion (size_type from, size_type to);
-    // Call after inserting elements directly into the raw container
-
-  public:
-    // Convenient replacement of elements (automatic proxy detachment)
-    void replace (size_type index, raw_value_type const &);
-    //    template<typename Iter> void replace (size_type index, Iter, Iter);
-
-    void swap_elements (size_type index1, size_type index2);
-
-    bool is_valid () const; // Check the class invariant (for testing purposes)
-
-  private:
-    // Overloads for insertions with/without useful std::distance
-    template<typename Iter>
-    void insert (iterator iter, Iter from, Iter to, std::forward_iterator_tag)
-      // Define here for MSVC6 compatibility
-    {
-      assert (iter.ptr == this);
-      size_type count = std::distance (from, to);
-
-      // Add empty proxy pointers for the new value(s) (could throw)
-      m_proxies.insert (m_proxies.begin() + iter.index, count, pointer_impl());
-
-      try
-        {
-          // Insert the new element(s) into the real container (could throw)
-          raw_container().insert(
-              raw_container().begin() + iter.index,
-              from,
-              to);
-
-          try
-            {
-              // Create new proxies for the new elements (could throw)
-              write_proxies (iter.index, iter.index + count);
-            }
-
-          catch (...)
-            {
-              raw_container().erase(
-                  raw_container().begin() + iter.index,
-                  raw_container().begin() + iter.index + count);
-
-              throw;
-            }
-        }
-
-      catch (...)
-        {
-          m_proxies.erase(
-              m_proxies.begin() + iter.index,
-              m_proxies.begin() + iter.index + count);
-
-          throw;
-        }
-
-      // Adjust any proxies after the inserted elements (nothrow)
-      adjust_proxies(
-          m_proxies.begin() + iter.index + count,
-          m_proxies.end(),
-          static_cast<difference_type> (count));
-    }
-
-    template<typename Iter>
-    void insert (iterator iter, Iter from, Iter to, std::input_iterator_tag)
-      // Define here for MSVC6 compatibility
-    {
-      // insert overload for iterators where we *can't* get distance()
-      // so just insert elements one at a time
-      while (from != to)
-        {
-          iter = insert (iter, *from++) + 1;
-        }
-    }
-
-  private:
-    typedef boost::shared_ptr<shared_proxy> pointer_impl;
-
-    typedef typename mpl::apply1<Generator, pointer_impl>::type
-      pointer_container;
-
-#if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
-    typedef detail::msvc6_iterator<pointer_container>::type pointer_iterator;
-#else
-    typedef typename pointer_container::iterator pointer_iterator;
-#endif
-
-#if defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
-    // Proxies need mutable access, and can't be friends with MSVC6
-  public:
-#endif
-    Container &raw_container();
-
-  private:
-    void adjust_proxies (pointer_iterator, pointer_iterator, difference_type);
-    void write_proxies (size_type, size_type);
-    bool clear_proxy (pointer_impl &);         // detach and do not reset
-    void clear_proxies (size_type, size_type); // detach and do not reset
-    void claim_all_proxies (); // Makes all proxies point at this object
-
-  private:
-    held_type m_held_obj;
-    pointer_container m_proxies;
-  };
-
-  template<class Container, class Holder, class Generator>
-  container_proxy<Container, Holder, Generator>
-  ::container_proxy ()
-    : m_held_obj (Holder::create()),
-    m_proxies ()
-  {
-    // Container is empty - no further processing
-  }
-
-  template<class Container, class Holder, class Generator>
-  container_proxy<Container, Holder, Generator>
-  ::container_proxy (held_type const &held)
-    : m_held_obj (Holder::copy (held)),
-    m_proxies (size())
-  {
-    write_proxies (0, size());
-  }
-
-  template<class Container, class Holder, class Generator>
-  container_proxy<Container, Holder, Generator>
-  ::container_proxy (container_proxy const &copy)
-    : m_held_obj (Holder::copy (copy.m_held_obj)),
-    m_proxies (size())
-  {
-    write_proxies (0, size()); // Create our own proxies for the copied values
-  }
-
-  template<class Container, class Holder, class Generator>
-  container_proxy<Container, Holder, Generator> &
-  container_proxy<Container, Holder, Generator>
-  ::operator= (container_proxy const &copy)
-  {
-    container_proxy<Container, Holder, Generator> temp (copy);
-    // This could throw, but none of the remaining operations can
-
-    Holder::swap (m_held_obj, temp.m_held_obj);
-    std::swap (m_proxies, temp.m_proxies);
-
-    claim_all_proxies ();
-    temp.claim_all_proxies ();  // Prepare for detach
-
-    return *this;
-    // temp destruction detaches any proxies that used to belong to us
-  }
-
-  template<class Container, class Holder, class Generator>
-  container_proxy<Container, Holder, Generator>
-  ::~container_proxy ()
-  {
-    // Copy original values into any proxies being shared by external pointers
-    clear_proxies (0, size());
-    Holder::pre_destruction (m_held_obj);
-  }
-
-  template<class Container, class Holder, class Generator>
-  Container &
-  container_proxy<Container, Holder, Generator>
-  ::raw_container ()
-  {
-    return Holder::get (m_held_obj);
-  }
-
-  template<class Container, class Holder, class Generator>
-  Container const &
-  container_proxy<Container, Holder, Generator>
-  ::raw_container () const
-  {
-    return Holder::get (m_held_obj);
-  }
-
-  template<class Container, class Holder, class Generator>
-  void container_proxy<Container, Holder, Generator>::reserve (size_type size)
-  {
-    raw_container().reserve (size);
-    m_proxies.reserve (size);
-  }
-
-  template<class Container, class Holder, class Generator>
-  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::reference
-  container_proxy<Container, Holder, Generator>
-  ::at (size_type index)
-  {
-    pointer_impl const &ptr = m_proxies.BOOST_PYTHON_INDEXING_AT (index);
-    assert (ptr->owner() == this);
-    assert (ptr->index() == index);
-    return reference (ptr);
-  }
-
-  template<class Container, class Holder, class Generator>
-  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::const_reference
-  container_proxy<Container, Holder, Generator>
-  ::at (size_type index) const
-  {
-    pointer_impl const &ptr = m_proxies.BOOST_PYTHON_INDEXING_AT (index);
-    assert (ptr->owner() == this);
-    assert (ptr->index() == index);
-    return const_reference (ptr);
-  }
-
-  template<class Container, class Holder, class Generator>
-  void
-  container_proxy<Container, Holder, Generator>
-  ::replace (size_type index, raw_value_type const &copy)
-  {
-    detach_proxy (index);
-    raw_container().BOOST_PYTHON_INDEXING_AT (index) = copy;
-    write_proxies (index, index + 1);
-  }
-
-  template<class Container, class Holder, class Generator>
-  void
-  container_proxy<Container, Holder, Generator>
-  ::swap_elements (size_type index1, size_type index2)
-  {
-    pointer_impl &ptr1 = m_proxies[index1];
-    pointer_impl &ptr2 = m_proxies[index2];
-
-    assert (ptr1->owner() == this);
-    assert (ptr2->owner() == this);
-    assert (ptr1->index() == index1);
-    assert (ptr2->index() == index2);
-
-    // Swap produces the diagrammed transformation. Any external
-    // pointers that refer to proxy1 or proxy2 will end up still
-    // pointing to their original (now relocated) values.
-    //
-    // .. ptr1 .. ptr2 ..     .. ptr1 .. ptr2  ..  (m_proxies)
-    //      |      |                 \  /
-    //      |      |                  \/
-    //      |      |                  /\.
-    //      V      V                 /  \.
-    //   proxy1  proxy2  -->    proxy1  proxy2
-    //      |      |                 \  /
-    //      |      |                  \/
-    //      |      |                  /\.
-    //      V      V                 /  \.
-    //  .. v1 ... v2 ..         .. v2 .. v1 ..  (raw_container)
-
-    std::swap (ptr1->m_index, ptr2->m_index);
-    std::swap (ptr1, ptr2);
-    std::swap (raw_container()[index1], raw_container()[index2]);
-
-    assert (m_proxies[index1]->index() == index1);
-    assert (m_proxies[index2]->index() == index2);
-  }
-
-  template<class Container, class Holder, class Generator>
-  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
-  container_proxy<Container, Holder, Generator>::erase (iterator iter)
-  {
-    return erase (iter, iter + 1);
-  }
-
-  template<class Container, class Holder, class Generator>
-  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
-  container_proxy<Container, Holder, Generator>::erase(
-      iterator from, iterator to)
-  {
-    assert (from.ptr == this);
-    assert (to.ptr == this);
-
-    // Detach and remove the proxies for the about-to-be-erased elements
-    prepare_erase (from.index, to.index);
-
-    // Erase the elements from the real container
-    raw_iterator result
-      = raw_container().erase(
-          raw_container().begin() + from.index,
-          raw_container().begin() + to.index);
-
-    return iterator (this, result);
-  }
-
-  template<class Container, class Holder, class Generator>
-  BOOST_DEDUCED_TYPENAME container_proxy<Container, Holder, Generator>::iterator
-  container_proxy<Container, Holder, Generator>::insert(
-      iterator iter, raw_value_type const &copy)
-  {
-    // Use the iterator-based version by treating the value as an
-    // array of size one (see section 5.7/4 of the C++98 standard)
-    insert (iter, &copy, (&copy) + 1, std::random_access_iterator_tag());
-
-    return iter;
-  }
-
-  template<class Container, class Holder, class Generator>
-  bool container_proxy<Container, Holder, Generator>::clear_proxy(
-      pointer_impl &ptr)
-  {
-    // Warning - this can break the class invariant. Use only when the
-    // pointer is about to be overwritten or removed from m_proxies
-
-    assert (ptr->owner() == this);
-
-    if (!ptr.unique())
-      {
-        ptr->detach (); // Cause proxy to copy element value
-        return true;
-      }
-
-    else
-      {
-        // If the pointer isn't shared, don't bother causing a copy of
-        // the container element, since the proxy is about to be
-        // deleted or reused.
-        return false;
-      }
-  }
-
-  template<class Container, class Holder, class Generator>
-  void container_proxy<Container, Holder, Generator>::clear_proxies(
-      size_type from_index, size_type to_index)
-  {
-    while (from_index != to_index)
-      {
-        clear_proxy (m_proxies[from_index]);
-        ++from_index;
-      }
-  }
-
-  template<class Container, class Holder, class Generator>
-  void container_proxy<Container, Holder, Generator>
-  ::detach_proxy (size_type index)
-  {
-    pointer_impl &ptr = m_proxies[index];
-
-    assert (ptr->index() == index);
-
-    if (clear_proxy (ptr))
-      {
-        // To maintain class invariant
-        ptr.reset (new shared_proxy (this, index));
-      }
-  }
-
-  template<class Container, class Holder, class Generator>
-  void container_proxy<Container, Holder, Generator>::detach_proxies(
-      size_type from_index, size_type to_index)
-  {
-    while (from_index != to_index)
-      {
-        detach_proxy (from_index);
-        ++from_index;
-      }
-  }
-
-  template<class Container, class Holder, class Generator>
-  void container_proxy<Container, Holder, Generator>
-  ::prepare_erase (size_type from_index, size_type to_index)
-  {
-    difference_type deleting = to_index - from_index;
-    pointer_iterator erase_begin = m_proxies.begin() + from_index;
-    pointer_iterator erase_end = m_proxies.begin() + to_index;
-
-    // Adjust the indexes of any trailing proxies
-    adjust_proxies (erase_end, m_proxies.end(), -deleting);
-
-    // Detach any proxies without updating our pointers to them
-    clear_proxies (from_index, to_index);
-
-    // Remove the pointers
-    m_proxies.erase (erase_begin, erase_end);
-  }
-
-  template<class Container, class Holder, class Generator>
-  void container_proxy<Container, Holder, Generator>::notify_insertion(
-      size_type from_index, size_type to_index)
-  {
-    size_type count = to_index - from_index;
-
-    m_proxies.insert(
-        m_proxies.begin() + from_index, count, pointer_impl());
-
-    try
-      {
-        write_proxies (from_index, to_index); // Could throw
-      }
-
-    catch (...)
-      {
-        m_proxies.erase(
-            m_proxies.begin() + from_index,
-            m_proxies.begin() + to_index);
-
-        throw;
-      }
-
-    // Adjust any proxies after the inserted elements (nothrow)
-    adjust_proxies(
-        m_proxies.begin() + to_index,
-        m_proxies.end(),
-        static_cast<difference_type> (count));
-  }
-
-  template<class Container, class Holder, class Generator>
-  void container_proxy<Container, Holder, Generator>::adjust_proxies(
-      pointer_iterator from,
-      pointer_iterator to,
-      difference_type offset)
-  {
-    while (from != to)
-      {
-        (*from)->m_index += offset;
-        ++from;
-      }
-  }
-
-  template<class Container, class Holder, class Generator>
-  void container_proxy<Container, Holder, Generator>::write_proxies(
-      size_type from, size_type to)
-  {
-    // (over)write proxy pointers in the given range. Re-uses existing
-    // shared_proxy objects where possible. Does not call detach_proxy
-    // since it is assumed that the original values could have already
-    // been modified and copying them now would be wrong.
-
-    while (from != to)
-      {
-        pointer_impl &ptr = m_proxies[from];
-
-        if ((ptr.get() == 0) || (!ptr.unique()))
-          {
-            // Either no proxy yet allocated here, or there is one
-            // but it is being shared by an external pointer.
-            ptr.reset (new shared_proxy (this, from));
-          }
-
-        else
-          {
-            // Re-use the existing object since we have the only pointer to it
-            assert (ptr->owner() == this);
-            ptr->m_index = from;
-          }
-
-        ++from;
-      }
-  }
-
-  template<class Container, class Holder, class Generator>
-  void container_proxy<Container, Holder, Generator>::claim_all_proxies ()
-  {
-    for (pointer_iterator iter = m_proxies.begin();
-         iter != m_proxies.end();
-         ++iter)
-      {
-        (*iter)->m_owner_ptr = this;
-      }
-  }
-
-  template<class Container, class Holder, class Generator>
-  bool container_proxy<Container, Holder, Generator>::is_valid () const
-  {
-    bool ok = size() == m_proxies.size(); // Sizes must match
-
-    for (size_type count = 0; ok && (count < size()); ++count)
-      {
-        pointer_impl const &ptr = m_proxies[count];
-
-        ok = ptr.get() && (ptr->owner() == this) && (ptr->index() == count)
-          && !ptr->m_element_ptr.get();
-      }
-
-    return ok;
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // ContainerTraits implementation for container_proxy instances
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename Container>
-  struct container_proxy_traits : random_access_sequence_traits<Container>
-  {
-    typedef Container container;
-    typedef typename container::raw_value_type value_type; // insert, ...
-    typedef typename container::raw_value_type key_type;   // find, count, ...
-    typedef typename container::reference reference;  // return values
-
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
-        value_param;
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
-        key_param;
-
-#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-    // value_traits for the reference type (i.e. our element_proxy
-    // instance) supplies a custom visit_container_class. Compilers
-    // without partial specialization need help here.
-
-    typedef element_proxy_traits<Container> value_traits_type;
-
-    // Hide base class visit_container_class, which would call the
-    // unspecialized value_traits version
-    template<typename PythonClass, typename Policy>
-    static void visit_container_class(
-        PythonClass &pyClass, Policy const &policy)
-    {
-      value_traits_type::visit_container_class (pyClass, policy);
-    }
-#endif
-  };
-
-#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  namespace detail {
-    ///////////////////////////////////////////////////////////////////////
-    // algorithms support for container_proxy instances
-    ///////////////////////////////////////////////////////////////////////
-
-    template <typename RawContainer, typename Holder, typename Generator>
-    class algorithms_selector<container_proxy<RawContainer, Holder, Generator> >
-    {
-      typedef container_proxy<RawContainer, Holder, Generator> Container;
-
-      typedef container_proxy_traits<Container>       mutable_traits;
-      typedef container_proxy_traits<Container const> const_traits;
-
-    public:
-      typedef default_algorithms<mutable_traits> mutable_algorithms;
-      typedef default_algorithms<const_traits>   const_algorithms;
-    };
-  }
-#endif
-  template<
-      class Container,
-      method_set_type MethodMask = all_methods,
-      class Traits = container_proxy_traits<Container>
-  >
-  struct container_proxy_suite
-    : container_suite<Container, MethodMask, default_algorithms<Traits> >
-  {
-  };
-
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_CONTAINER_PROXY_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_suite.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_suite.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_suite.hpp	1970-01-01 00:00:00 +0000
@@ -1,54 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file container_suite.hpp
-//
-// Top-level interface to the container suite.
-//
-// History
-// =======
-// 2003/ 8/23   rmg     File creation
-// 2003/ 9/ 8   rmg     Extracted trait facilities into container_traits.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: container_suite.hpp,v 1.1.2.7 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_CONTAINER_SUITE_HPP
-#define BOOST_PYTHON_INDEXING_CONTAINER_SUITE_HPP
-
-#include <indexing_suite/methods.hpp>
-#include <indexing_suite/algorithms.hpp>
-#include <indexing_suite/visitor.hpp>
-
-#include <boost/python/return_by_value.hpp>
-#include <boost/python/return_value_policy.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  typedef boost::python::return_value_policy<boost::python::return_by_value>
-  default_container_policies;
-
-  template<
-      class Container,
-      method_set_type MethodMask = all_methods,  // All supported by algorithms
-      class Algorithms
-          = algorithms<Container>
-  >
-  struct container_suite
-    : public visitor<Algorithms, default_container_policies, MethodMask>
-  {
-    typedef Algorithms algorithms;
-
-    template<typename Policy>
-    static visitor<Algorithms, Policy, MethodMask>
-    with_policies (Policy const &policy)
-    {
-      return visitor <Algorithms, Policy, MethodMask> (policy);
-    }
-  };
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_CONTAINER_SUITE_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_traits.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_traits.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/container_traits.hpp	1970-01-01 00:00:00 +0000
@@ -1,160 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file container_traits.hpp
-//
-// Traits information about entire containers for use in determining
-// what Python methods to provide.
-//
-// History
-// =======
-// 2003/ 8/23   rmg     File creation as container_suite.hpp
-// 2003/ 9/ 8   rmg     Renamed container_traits.hpp
-// 2003/10/28   rmg     Split container-specific versions into separate headers
-// 2004/ 1/28   rmg     Convert to bitset-based feature selection
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: container_traits.hpp,v 1.1.2.15 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_CONTAINER_TRAITS_HPP
-#define BOOST_PYTHON_INDEXING_CONTAINER_TRAITS_HPP
-
-#include <indexing_suite/suite_utils.hpp>
-#include <indexing_suite/methods.hpp>
-#include <indexing_suite/value_traits.hpp>
-
-#include <boost/type_traits.hpp>
-#include <boost/call_traits.hpp>
-#include <boost/mpl/if.hpp>
-#include <boost/type_traits/ice.hpp>
-#include <boost/iterator/iterator_traits.hpp>
-
-namespace boost { namespace python { namespace indexing {
-#if BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
-  // MSVC6 has problems with get_signature if parameter types have
-  // top-level const qualification (e.g. int const). Unfortunately,
-  // this is exactly what happens with boost::call_traits, so we
-  // substitute a really dumb version of it instead.
-
-  template<typename T> struct broken_call_traits {
-    typedef T const & param_type;
-  };
-# define BOOST_PYTHON_INDEXING_CALL_TRAITS broken_call_traits
-#else
-# define BOOST_PYTHON_INDEXING_CALL_TRAITS ::boost::call_traits
-#endif
-
-  /////////////////////////////////////////////////////////////////////////
-  // Lowest common denominator traits - applicable to real containers
-  // and iterator pairs
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename Container, typename ValueTraits = detail::no_override>
-  struct base_container_traits
-  {
-    typedef base_container_traits<Container, ValueTraits> self_type;
-
-  protected:
-    BOOST_STATIC_CONSTANT(
-        bool, is_mutable = ! boost::is_const<Container>::value);
-
-  public:
-    typedef Container container;
-
-    typedef BOOST_DEDUCED_TYPENAME container::value_type value_type;
-
-    typedef BOOST_DEDUCED_TYPENAME mpl::if_<
-        is_const<container>,
-        BOOST_DEDUCED_TYPENAME container::const_iterator,
-        BOOST_DEDUCED_TYPENAME container::iterator
-      >::type iterator;
-
-    typedef typename ::boost::iterator_reference<iterator>::type reference;
-
-    typedef value_type key_type; // Used for find, etc.
-    typedef typename container::size_type size_type;
-    typedef typename make_signed<size_type>::type index_type;
-    // at(), operator[]. Signed to support Python -ve indexes
-
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS<value_type>::param_type
-        value_param;
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS<key_type>::param_type
-        key_param;
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS<index_type>::param_type
-        index_param;
-
-    // Allow client code to replace the default value traits via our
-    // second (optional) template parameter
-    typedef value_traits<value_type> default_value_traits;
-    typedef typename detail::maybe_override<
-        default_value_traits, ValueTraits>::type value_traits_type;
-
-    // Forward visit_container_class to value_traits_type
-    template<typename PythonClass, typename Policy>
-    static void visit_container_class(
-        PythonClass &pyClass, Policy const &policy)
-    {
-      value_traits_type::visit_container_class (pyClass, policy);
-    }
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // ContainerTraits for sequences with random access - std::vector,
-  // std::deque and the like
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename Container, typename ValueTraits = detail::no_override>
-  class random_access_sequence_traits
-    : public base_container_traits<Container, ValueTraits>
-  {
-    typedef base_container_traits<Container, ValueTraits> base_class;
-
-  public:
-    typedef typename base_class::value_traits_type value_traits_type;
-
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = (
-              method_len
-            | method_getitem
-            | method_getitem_slice
-
-            | detail::method_set_if<
-                  value_traits_type::equality_comparable,
-                    method_index
-                  | method_contains
-                  | method_count
-              >::value
-
-            | detail::method_set_if<
-                  base_class::is_mutable,
-                    method_setitem
-                  | method_setitem_slice
-                  | method_delitem
-                  | method_delitem_slice
-                  | method_reverse
-                  | method_append
-                  | method_insert
-                  | method_extend
-              >::value
-
-            | detail::method_set_if<
-                  type_traits::ice_and<
-                      base_class::is_mutable,
-                      value_traits_type::less_than_comparable
-                  >::value,
-                  method_sort
-              >::value
-
-        ));
-
-        // Not supported: method_iter, method_has_key
-  };
-
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_CONTAINER_SUITE_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/deque.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/deque.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/deque.hpp	1970-01-01 00:00:00 +0000
@@ -1,61 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file deque.hpp
-//
-// Indexing algorithms support for std::deque instances
-//
-// History
-// =======
-// 2003/10/28   rmg     File creation from algo_selector.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: deque.hpp,v 1.1.2.6 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_DEQUE_HPP
-#define BOOST_PYTHON_INDEXING_DEQUE_HPP
-
-#include <indexing_suite/container_traits.hpp>
-#include <indexing_suite/container_suite.hpp>
-#include <indexing_suite/algorithms.hpp>
-#include <deque>
-
-namespace boost { namespace python { namespace indexing {
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  namespace detail {
-    ///////////////////////////////////////////////////////////////////////
-    // algorithms support for std::deque instances
-    ///////////////////////////////////////////////////////////////////////
-
-    template <class T, class Allocator>
-    class algorithms_selector<std::deque<T, Allocator> >
-    {
-      typedef std::deque<T, Allocator> Container;
-
-      typedef random_access_sequence_traits<Container>       mutable_traits;
-      typedef random_access_sequence_traits<Container const> const_traits;
-
-    public:
-      typedef default_algorithms<mutable_traits> mutable_algorithms;
-      typedef default_algorithms<const_traits>   const_algorithms;
-    };
-  }
-#endif
-
-  template<
-    class Container,
-    method_set_type MethodMask = all_methods,
-    class Traits = random_access_sequence_traits<Container>
-  >
-  struct deque_suite
-    : container_suite<Container, MethodMask, default_algorithms<Traits> >
-  {
-  };
-
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_DEQUE_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/element_proxy.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/element_proxy.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/element_proxy.hpp	1970-01-01 00:00:00 +0000
@@ -1,188 +0,0 @@
-// Header file element_proxy.hpp
-//
-// Proxy objects for invidivual elements in a container wrapped by
-// container_proxy
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/ 9/15   rmg     File creation from container_proxy.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: element_proxy.hpp,v 1.1.2.10 2003/12/03 12:18:51 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_ELEMENT_PROXY_HPP
-#define BOOST_PYTHON_INDEXING_ELEMENT_PROXY_HPP
-
-#include <indexing_suite/shared_proxy_impl.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/get_pointer.hpp>
-#include <boost/utility/addressof.hpp>
-#include <boost/detail/workaround.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  template<typename ContainerProxy>
-  class element_proxy
-  {
-  public:
-    typedef typename ContainerProxy::shared_proxy proxy_type;
-    typedef typename ContainerProxy::raw_value_type raw_value_type;
-    typedef typename ContainerProxy::size_type size_type;
-    typedef boost::shared_ptr<proxy_type> proxy_pointer;
-
-    typedef typename proxy_type::value_type value_type;
-    typedef typename proxy_type::reference reference;
-    typedef typename proxy_type::pointer pointer;
-    typedef typename proxy_type::iterator_category iterator_category;
-    typedef typename proxy_type::difference_type difference_type;
-
-    typedef value_type element_type;      // Alias for register_ptr_to_python
-
-    element_proxy () : m_ptr () { }
-    explicit element_proxy (proxy_type *ptr) : m_ptr (ptr) { }
-    explicit element_proxy (proxy_pointer const &ptr) : m_ptr (ptr) { }
-
-    explicit element_proxy (raw_value_type const &val)
-      : m_ptr (new proxy_type(val))
-    {
-      // Create new standalone value (i.e. detached)
-    }
-
-    reference operator* () const { return m_ptr->operator*(); }
-    pointer operator-> () const { return (*m_ptr).operator->(); }
-    pointer get () const { return operator->(); }  // Alias for pointer_holder
-
-    // Implicit conversion to raw_value_type
-    operator reference () const { return operator*(); }
-
-#if BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
-    // The implicit conversion doesn't work on MSVC6, so help it along
-    // a little.
-    bool operator== (value_type const &val) const { return (**this) == val; }
-    bool operator!= (value_type const &val) const { return (**this) != val; }
-    bool operator< (value_type const &val) const { return (**this) < val; }
-    bool operator> (value_type const &val) const { return (**this) > val; }
-#endif
-
-    element_proxy &operator= (value_type const &copy)
-    {
-      proxy_type &proxy = *m_ptr;
-      ContainerProxy *container = proxy.owner();
-      size_type index = proxy.index();
-
-      if (container)
-        {
-          container->replace (index, copy);
-          // Proxy was attached before, but is now detached. Make sure
-          // we now refer to the new element, instead of the detached
-          // copy of the old element
-          m_ptr = container->at (index).m_ptr;
-
-          // Note: in the special case that this we and the container
-          // proxy itself have the only references to the
-          // shared_proxy_impl, it is not necessary to first detach
-          // the proxy. Maybe best to implement when changing to
-          // intrusive_ptr instead of shared_ptr.
-        }
-
-      else
-        {
-          *proxy = copy;
-        }
-
-      return *this;
-    }
-
-    element_proxy &operator= (element_proxy const &copy)
-    {
-      // Required to make sorting a container_proxy work
-      return (*this) = *copy;
-    }
-
-    size_t use_count() const { return m_ptr.use_count(); } // For debugging
-
-  private:
-    proxy_pointer m_ptr;
-  };
-
-  template<typename ContainerProxy>
-  class const_element_proxy
-  {
-  public:
-    typedef element_proxy<ContainerProxy> base_type;
-    typedef typename base_type::proxy_type proxy_type;
-    typedef typename base_type::proxy_pointer proxy_pointer;
-    typedef typename base_type::raw_value_type raw_value_type;
-
-    typedef typename proxy_type::value_type const value_type;
-    typedef value_type &reference;
-    typedef value_type *pointer;
-    typedef typename base_type::iterator_category iterator_category;
-    typedef typename base_type::difference_type difference_type;
-
-    const_element_proxy () : m_base () { }
-    explicit const_element_proxy (proxy_type *ptr) : m_base (ptr) { }
-
-    explicit const_element_proxy (proxy_pointer const &ptr) : m_base (ptr) {}
-
-    const_element_proxy (const_element_proxy<ContainerProxy> const &copy)
-      : m_base (copy.m_base)
-    {
-    }
-
-    const_element_proxy (element_proxy<ContainerProxy> const &copy)
-      : m_base (copy)
-    {
-    }
-
-    explicit const_element_proxy (raw_value_type const &val)
-      : m_base (new proxy_type(val))
-    {
-    }
-
-    reference operator* () const { return *m_base; }
-    pointer operator-> () const { return m_base.operator->(); }
-
-    // Implicit conversion to raw_value_type const &
-    operator reference () const { return *m_base; }
-
-#if BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
-    // The implicit conversion doesn't work on MSVC6, so help it along
-    // a little.
-    bool operator== (value_type const &val) const { return m_base == val; }
-    bool operator!= (value_type const &val) const { return m_base != val; }
-    bool operator< (value_type const &val) const { return m_base < val; }
-    bool operator> (value_type const &val) const { return m_base > val; }
-#endif
-
-    size_t use_count() const { return m_base.use_count(); } // For debugging
-
-  private:
-    base_type m_base;
-  };
-
-#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
-}} // namespace python::indexing
-#endif
-
-  template<typename ContainerProxy>
-  typename ContainerProxy::raw_value_type *
-  get_pointer (python::indexing::element_proxy<ContainerProxy> const &proxy)
-  {
-    return ::boost::addressof (*proxy);
-  }
-
-#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
-    // Don't hide these other get_pointer overloads
-    using boost::get_pointer;
-}} // namespace python::indexing
-#endif
-}
-
-#endif // BOOST_PYTHON_INDEXING_ELEMENT_PROXY_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/element_proxy_traits.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/element_proxy_traits.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/element_proxy_traits.hpp	1970-01-01 00:00:00 +0000
@@ -1,90 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file element_proxy_traits.hpp
-//
-// Note: element_proxy.hpp must be included before this header
-//
-// This is a separate header so that element_proxy.hpp is not
-// dependant on register_ptr_to_python.hpp. This avoids a problem with
-// two-phase name lookup, where register_ptr_to_python must be
-// included *after* the element_proxy overload of boost::get_pointer
-// is declared.
-//
-// History
-// =======
-// 2003/10/23   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: element_proxy_traits.hpp,v 1.1.2.5 2003/12/05 17:36:14 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_ELEMENT_PROXY_TRAITS_HPP
-#define BOOST_PYTHON_INDEXING_ELEMENT_PROXY_TRAITS_HPP
-
-#include <indexing_suite/element_proxy.hpp>
-#include <indexing_suite/value_traits.hpp>
-#include <boost/python/register_ptr_to_python.hpp>
-#include <boost/python/implicit.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  template<typename ContainerProxy>
-  struct element_proxy_traits
-    : public value_traits<
-          BOOST_DEDUCED_TYPENAME ContainerProxy::raw_value_type>
-  {
-    typedef element_proxy<ContainerProxy> element_proxy_type;
-    typedef typename ContainerProxy::raw_value_type raw_value_type;
-    typedef value_traits<raw_value_type> base_type;
-
-    // Wrap the base class versions of the comparisons using
-    // indirection
-    struct less
-      : std::binary_function<element_proxy_type, element_proxy_type, bool>
-    {
-      typename base_type::less m_base_compare;
-
-      bool operator()(
-          element_proxy_type const &p1, element_proxy_type const &p2) const
-      {
-        return m_base_compare (*p1, *p2);
-      }
-    };
-
-    struct equal_to
-      : std::binary_function<raw_value_type, element_proxy_type, bool>
-    {
-      // First param is raw_value_type to interface smoothly with the
-      // bind1st used in default_algorithms::find
-
-      typename base_type::equal_to m_base_compare;
-
-      bool operator()(
-          raw_value_type const &v, element_proxy_type const &p) const
-      {
-        return m_base_compare (v, *p);
-      }
-    };
-
-    template<typename PythonClass, typename Policy>
-    static void visit_container_class (PythonClass &, Policy const &)
-    {
-      register_ptr_to_python<element_proxy_type>();
-      implicitly_convertible<raw_value_type, element_proxy_type>();
-    }
-  };
-
-#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  // value_traits partial specialization for element_proxy instances
-  template<typename ContainerProxy>
-  struct value_traits<element_proxy<ContainerProxy> >
-    : element_proxy_traits<ContainerProxy>
-  {
-  };
-#endif
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_ELEMENT_PROXY_TRAITS_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/int_slice_helper.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/int_slice_helper.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/int_slice_helper.hpp	1970-01-01 00:00:00 +0000
@@ -1,252 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file int_slice_helper.hpp
-//
-// History
-// =======
-// 2003/10/13   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: int_slice_helper.hpp,v 1.1.2.10 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP
-#define BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP
-
-# include <boost/python/errors.hpp>
-# include <indexing_suite/workaround.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  template<typename Algorithms, typename SliceType>
-  struct int_slice_helper
-  {
-    // Works with a SliceType that provides an int-like index_type
-    // that is convertible to the algorithm's index_param
-
-    typedef Algorithms algorithms_type;
-    typedef SliceType slice_type;
-
-    typedef typename algorithms_type::container container;
-    typedef typename algorithms_type::reference reference;
-    typedef typename algorithms_type::value_param value_param;
-    typedef typename algorithms_type::container_traits container_traits;
-    typedef typename slice_type::index_type index_type;
-
-    int_slice_helper (container &c, slice_type const &);
-
-    bool next();
-
-    reference current () const;
-    void write (value_param val);
-    void erase_remaining () const;
-
-  private:
-    void assign (value_param val) const;
-    void insert (value_param val);
-
-  private:
-    slice_type m_slice;
-    container *m_ptr;
-    index_type m_pos;
-  };
-
-  template<typename Algorithms, typename SliceType>
-  int_slice_helper<Algorithms, SliceType>
-  ::int_slice_helper (container &c, slice_type const &sl)
-    : m_slice (sl),
-    m_ptr (&c),
-    m_pos (-1)
-  {
-  }
-
-  template<typename Algorithms, typename SliceType>
-  bool
-  int_slice_helper<Algorithms, SliceType>::next()
-  {
-    bool result = false; // Assume the worst
-
-    if (m_pos == -1)
-      {
-        // First time call - get to start of the slice (if any)
-        m_pos = m_slice.start();
-        result = m_slice.in_range (m_pos);
-      }
-
-    else if (m_slice.in_range (m_pos))
-      {
-        // Subsequent calls - advance by the slice's stride
-        m_pos += m_slice.step();
-        result = m_slice.in_range (m_pos);
-      }
-
-    return result;
-  }
-
-  template<typename Algorithms, typename SliceType>
-  typename int_slice_helper<Algorithms, SliceType>::reference
-  int_slice_helper<Algorithms, SliceType>::current () const
-  {
-    return algorithms_type::get (*m_ptr, m_pos);
-  }
-
-  template<typename Algorithms, typename SliceType>
-  void int_slice_helper<Algorithms, SliceType>::write (value_param val)
-  {
-    if (next())
-      {
-        assign (val);
-      }
-
-    else
-      {
-        insert (val);
-      }
-  }
-
-  template<typename Algorithms, typename SliceType>
-  void int_slice_helper<Algorithms, SliceType>::assign (value_param val) const
-  {
-    algorithms_type::assign (*m_ptr, m_pos, val);
-  }
-
-  namespace detail {
-    template<bool doit> struct maybe_insert {
-
-      // NOTE: use the name "apply_" instead of "apply" to avoid
-      // weirdo compiler crash in mpl/aux_/apply.hpp on MSVC7. Don't
-      // even ask how I arrived at this fix :-)
-
-      template<class Algorithms>
-      static void apply_(
-# if defined (BOOST_NO_MEMBER_TEMPLATES) \
-        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
-          // Can't explicitly instantiate member function - must let
-          // the compiler deduce the argument type from a dummy
-          // parameter. Same applies throughout
-          Algorithms *,
-# endif
-          typename Algorithms::container &,
-          typename Algorithms::index_param,
-          typename Algorithms::value_param)
-      {
-        PyErr_SetString(
-            PyExc_TypeError,
-            "container does not support insertion into slice");
-
-        boost::python::throw_error_already_set ();
-      }
-    };
-
-    template<> struct maybe_insert<true> {
-      template<class Algorithms>
-      static void apply_(
-# if defined (BOOST_NO_MEMBER_TEMPLATES) \
-        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
-          Algorithms *,
-# endif
-          typename Algorithms::container &c,
-          typename Algorithms::index_param i,
-          typename Algorithms::value_param v)
-      {
-        Algorithms::insert (c, i, v);
-      }
-    };
-  }
-
-  template<typename Algorithms, typename SliceType>
-  void int_slice_helper<Algorithms, SliceType>::insert (value_param val)
-  {
-    if (m_slice.step() != 1)
-      {
-        PyErr_SetString(
-            PyExc_ValueError, "attempt to insert via extended slice");
-
-        boost::python::throw_error_already_set ();
-      }
-
-    else
-      {
-        detail::maybe_insert<
-          detail::is_member<
-            container_traits::supported_methods, method_insert>::value>::
-# if defined (BOOST_NO_MEMBER_TEMPLATES) \
-  && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
-          apply_ (static_cast<Algorithms *>(0),
-# else
-          BOOST_NESTED_TEMPLATE apply_ <Algorithms>(
-# endif
-              *m_ptr, m_pos, val);
-
-        ++m_pos;  // Advance for any subsequent inserts
-      }
-  }
-
-  namespace detail {
-    template<bool doit> struct maybe_erase {
-      template<class Algorithms>
-      static void apply_(
-# if defined (BOOST_NO_MEMBER_TEMPLATES) \
-        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
-          Algorithms *,
-# endif
-          typename Algorithms::container &,
-          typename Algorithms::index_param,
-          typename Algorithms::index_param)
-      {
-        PyErr_SetString(
-            PyExc_TypeError, "container does not support item deletion");
-
-        boost::python::throw_error_already_set ();
-      }
-    };
-
-    template<> struct maybe_erase<true> {
-      template<class Algorithms>
-      static void apply_(
-# if defined (BOOST_NO_MEMBER_TEMPLATES) \
-        && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
-          Algorithms *,
-# endif
-          typename Algorithms::container &c,
-          typename Algorithms::index_param from,
-          typename Algorithms::index_param to)
-      {
-        Algorithms::erase_range (c, from, to);
-      }
-    };
-  }
-
-  template<typename Algorithms, typename SliceType>
-  void int_slice_helper<Algorithms, SliceType>::erase_remaining () const
-  {
-    if (m_slice.step() != 1)
-      {
-        PyErr_SetString(
-            PyExc_ValueError, "attempt to delete via extended slice");
-
-        boost::python::throw_error_already_set ();
-      }
-
-    else
-      {
-        detail::maybe_erase<
-          detail::is_member<
-            container_traits::supported_methods, method_delitem>::value>::
-
-# if defined (BOOST_NO_MEMBER_TEMPLATES) \
-  && defined (BOOST_MSVC6_MEMBER_TEMPLATES)
-          apply_ (static_cast<Algorithms *>(0),
-# else
-          BOOST_NESTED_TEMPLATE apply_ <Algorithms>(
-# endif
-              *m_ptr, m_pos, m_slice.stop());
-      }
-  }
-
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_INT_SLICE_HELPER_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/iterator_range.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/iterator_range.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/iterator_range.hpp	1970-01-01 00:00:00 +0000
@@ -1,261 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file iterator_range.hpp
-//
-// Emulate an STL container using a pair of iterators. Doesn't support
-// insertion or deletion, for the obvious reasons.
-//
-// History
-// =======
-// 2003/ 9/ 9   rmg     File creation as iterator_pair.hpp
-// 2003/10/27   rmg     Renamed iterator_range.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: iterator_range.hpp,v 1.1.2.7 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_ITERATOR_RANGE_HPP
-#define BOOST_PYTHON_INDEXING_ITERATOR_RANGE_HPP
-
-#include <stdexcept>
-#include <algorithm>
-#include <utility>
-#include <boost/type_traits.hpp>
-#include <boost/type_traits/ice.hpp>
-#include <boost/detail/workaround.hpp>
-#include <boost/iterator/iterator_traits.hpp>
-#include <indexing_suite/container_traits.hpp>
-#include <indexing_suite/container_suite.hpp>
-#include <indexing_suite/algorithms.hpp>
-#include <indexing_suite/iterator_traits.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  template<typename Iterator>
-  class iterator_range
-  {
-  private:
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <Iterator>::param_type
-        iterator_param;
-
-    typedef ::boost::detail::iterator_traits<Iterator> std_traits;
-
-  public:
-    typedef typename std_traits::reference       reference;
-    typedef Iterator                             iterator;
-    typedef typename std_traits::difference_type size_type;
-    typedef typename std_traits::difference_type difference_type;
-    typedef typename std_traits::value_type      value_type;
-    typedef typename std_traits::pointer         pointer;
-
-    typedef iterator                             const_iterator;
-    // Can't tell what the const version of our iterator should
-    // be. The client code will have to instantiate iterator_range
-    // directly with a const_iterator if that's what it wants.
-
-    // Also can't provide: allocator_type, reverse_iterator or
-    // const_reverse_iterator. Could probably provide (but don't)
-    // const_reference and const_pointer. These would be the same as
-    // reference and pointer if Iterator is itself a const_iterator.
-
-  public:
-    iterator_range (iterator_param, iterator_param);
-    iterator_range (std::pair<iterator, iterator> const &);
-
-    iterator begin() const;
-    iterator end() const;
-
-  public:
-    // Only sensible for random_access iterators
-    size_type size () const;
-    reference operator[] (size_type) const;
-    reference at (size_type) const;
-
-  private:
-    iterator m_begin;
-    iterator m_end;
-  };
-
-  // Array support function(s).
-  template<typename T> iterator_range<T *> make_iterator_range (T *, T*);
-
-#if !BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
-  template<typename T, std::size_t N> iterator_range<T *> make_iterator_range(
-      T (&array)[N]);
-
-  template<typename T, std::size_t N> T *begin (T (&array)[N]);
-  template<typename T, std::size_t N> T *end   (T (&array)[N]);
-
-# define BOOST_MAKE_ITERATOR_RANGE \
-      ::boost::python::indexing::make_iterator_range
-
-#else
-  // For compilers that can't deduce template argument array bounds
-# define BOOST_MAKE_ITERATOR_RANGE(array) \
-      ::boost::python::indexing::make_iterator_range ( \
-          (array), ((array) + sizeof(array) / sizeof((array)[0])))
-#endif
-
-  template<typename Iterator>
-  iterator_range<Iterator>::iterator_range(
-      iterator_param begin, iterator_param end)
-    : m_begin (begin),
-    m_end (end)
-  {
-  }
-
-  template<typename Iterator>
-  iterator_range<Iterator>
-  ::iterator_range (std::pair<iterator, iterator> const &pair)
-    : m_begin (pair.first),
-    m_end (pair.second)
-  {
-  }
-
-  template<typename Iterator>
-  typename iterator_range<Iterator>::iterator
-  iterator_range<Iterator>::begin() const
-  {
-    return m_begin;
-  }
-
-  template<typename Iterator>
-  typename iterator_range<Iterator>::iterator
-  iterator_range<Iterator>::end() const
-  {
-    return m_end;
-  }
-
-  template<typename Iterator>
-  typename iterator_range<Iterator>::size_type
-  iterator_range<Iterator>::size() const
-  {
-    return std::distance (begin(), end());
-  }
-
-  template<typename Iterator>
-  typename iterator_range<Iterator>::reference
-  iterator_range<Iterator>::operator[](size_type index) const
-  {
-    iterator temp (begin());
-    std::advance (temp, index);
-    return *temp;
-  }
-
-  template<typename Iterator>
-  typename iterator_range<Iterator>::reference
-  iterator_range<Iterator>::at (size_type index) const
-  {
-    if (index >= size())
-      {
-        throw std::out_of_range
-          (std::string ("iterator_range: index out of range"));
-      }
-
-    else
-      {
-        return (*this)[index];
-      }
-  }
-
-  template<typename T> iterator_range<T *> make_iterator_range (T *p1, T* p2)
-  {
-    return iterator_range<T *> (p1, p2);
-  }
-
-#if !BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
-  template<typename T, std::size_t N>
-  T *begin (T (&array)[N]) {
-    return array;
-  }
-
-  template<typename T, std::size_t N>
-  T *end (T (&array)[N]) {
-    return array + N;
-  }
-
-  template<typename T, std::size_t N>
-  iterator_range<T *> make_iterator_range (T (&array)[N]) {
-    return iterator_range<T *>(begin (array), end (array));
-  }
-#endif
-
-  template<typename Container, typename ValueTraits = detail::no_override>
-  class iterator_range_traits
-    : public base_container_traits<Container, ValueTraits>
-  {
-    typedef base_container_traits<Container, ValueTraits> base_class;
-
-    typedef ::boost::python::indexing::iterator_traits<
-      typename Container::iterator
-    > iterator_traits_type;
-
-  public:
-    typedef typename base_class::value_traits_type value_traits_type;
-
-  private:
-    // Methods that we *can't* support because of our value type
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        disabled_methods = (
-            detail::method_set_if<
-               type_traits::ice_not<
-                   value_traits_type::equality_comparable
-               >::value,
-                 method_index      // Impossible if !equality_comparable
-               | method_contains   // Impossible if !equality_comparable
-               | method_count      // Impossible if !equality_comparable
-            >::value
-
-          | detail::method_set_if<
-               type_traits::ice_not<
-                   value_traits_type::less_than_comparable
-               >::value,
-               method_sort         // Impossible if !less_than_comparable
-            >::value
-        ));
-
-  public:
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods =
-        iterator_traits_type::supported_methods & ~disabled_methods);
-  };
-
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  namespace detail {
-    ///////////////////////////////////////////////////////////////////////
-    // algorithms support for iterator_range instances
-    ///////////////////////////////////////////////////////////////////////
-
-    template <typename Iterator>
-    class algorithms_selector<iterator_range<Iterator> >
-    {
-      typedef iterator_range<Iterator> Container;
-
-      typedef iterator_range_traits<Container>       mutable_traits;
-      typedef iterator_range_traits<Container const> const_traits; // ?
-
-    public:
-      typedef default_algorithms<mutable_traits> mutable_algorithms;
-      typedef default_algorithms<const_traits>   const_algorithms;
-    };
-  }
-#endif
-
-  template<
-    class Container,
-    method_set_type MethodMask = all_methods,
-    class Traits = iterator_range_traits<Container>
-  >
-  struct iterator_range_suite
-    : container_suite<Container, MethodMask, default_algorithms<Traits> >
-  {
-  };
-
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_ITERATOR_RANGE_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/iterator_traits.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/iterator_traits.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/iterator_traits.hpp	1970-01-01 00:00:00 +0000
@@ -1,212 +0,0 @@
-// -*- mode:c++ -*-
-//
-// Header file iterator_traits.hpp
-//
-// Traits information about iterators for use in determining what
-// Python methods to support for a container.
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/ 8/23   rmg     File creation as iterator_suite.hpp
-// 2003/ 9/12   rmg     Renamed iterator_traits.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: iterator_traits.hpp,v 1.1.2.14 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_ITERATOR_TRAITS_HPP
-#define BOOST_PYTHON_INDEXING_ITERATOR_TRAITS_HPP
-
-#include <indexing_suite/suite_utils.hpp>
-#include <indexing_suite/methods.hpp>
-//#include <indexing_suite/workaround.hpp>
-
-//#include <boost/call_traits.hpp>
-//#include <boost/type_traits.hpp>
-#include <boost/iterator/iterator_traits.hpp>
-#include <boost/iterator/iterator_categories.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  //////////////////////////////////////////////////////////////////////////
-  // Indexing traits common base class
-  //////////////////////////////////////////////////////////////////////////
-
-  template<typename Iterator>
-  struct base_iterator_traits
-  {
-  private:
-    typedef ::boost::detail::iterator_traits<Iterator> std_traits;
-    typedef typename std_traits::reference reference;
-
-  public:
-    //    typedef Iterator                             iterator;
-    //    typedef typename std_traits::value_type      value_type;
-    //    typedef typename std_traits::difference_type difference_type;
-
-    BOOST_STATIC_CONSTANT(
-        bool, has_mutable_ref = is_mutable_ref<reference>::value);
-  };
-
-  //////////////////////////////////////////////////////////////////////////
-  // Indexing traits for input iterators
-  //////////////////////////////////////////////////////////////////////////
-
-  template<typename Iterator>
-  struct input_iterator_traits : base_iterator_traits<Iterator>
-  {
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = (
-            method_iter
-        ));
-  };
-
-  //////////////////////////////////////////////////////////////////////////
-  // Indexing traits for forward iterators
-  //////////////////////////////////////////////////////////////////////////
-
-  template<typename Iterator>
-  struct forward_iterator_traits
-    : public base_iterator_traits<Iterator>
-  {
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = (
-              method_len
-            | method_iter
-        ));
-  };
-
-  //////////////////////////////////////////////////////////////////////////
-  // Indexing traits for bidirectional iterators
-  //////////////////////////////////////////////////////////////////////////
-
-  template<typename Iterator>
-  struct bidirectional_iterator_traits
-    : public forward_iterator_traits<Iterator>
-  {
-    typedef forward_iterator_traits<Iterator> base_class;
-
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = (
-              base_class::supported_methods
-
-            | detail::method_set_if<
-                  base_class::has_mutable_ref,
-                  method_reverse
-              >::value
-        ));
-  };
-
-  //////////////////////////////////////////////////////////////////////////
-  // Indexing traits for random access iterators
-  //////////////////////////////////////////////////////////////////////////
-
-  template<typename Iterator>
-  struct random_access_iterator_traits
-    : public bidirectional_iterator_traits<Iterator>
-  {
-    typedef bidirectional_iterator_traits<Iterator> base_class;
-
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = (
-            (base_class::supported_methods & ~method_iter)
-
-            | method_getitem
-            | method_getitem_slice
-
-            | detail::method_set_if<
-                  base_class::has_mutable_ref,
-                  method_setitem
-                | method_setitem_slice
-              >::value
-
-            | method_index     // Assumes value is equality_comparable
-            | method_contains  // Assumes value is equality_comparable
-            | method_count     // Assumes value is equality_comparable
-
-            | detail::method_set_if<
-                  base_class::has_mutable_ref,
-                  method_sort
-              >::value         // Assumes value is less_than_comparable
-
-        ));
-  };
-
-  namespace iterator_detail {
-    // Some meta-progamming machinery to select the right
-    // indexing::iterator_traits template on the basis of
-    // BOOST_ITERATOR_CATEGORY
-
-    typedef char basic_iter_sizer[1];
-    typedef char forward_iter_sizer[2];
-    typedef char bidirectional_iter_sizer[3];
-    typedef char random_access_iter_sizer[4];
-
-    basic_iter_sizer         &sizer (void *);
-    forward_iter_sizer       &sizer (std::forward_iterator_tag *);
-    bidirectional_iter_sizer &sizer (std::bidirectional_iterator_tag *);
-    random_access_iter_sizer &sizer (std::random_access_iterator_tag *);
-
-    template<size_t Size> struct traits_by_size {
-      // Default implementation gives only the most basic support
-      template<typename Iterator>
-        struct traits {
-          typedef input_iterator_traits<Iterator> type;
-        };
-    };
-
-    template<>
-    struct traits_by_size<sizeof(forward_iter_sizer)> {
-      template<typename Iterator>
-        struct traits {
-          typedef forward_iterator_traits<Iterator> type;
-        };
-    };
-
-    template<>
-    struct traits_by_size<sizeof(bidirectional_iter_sizer)> {
-      template<typename Iterator>
-        struct traits {
-          typedef bidirectional_iterator_traits<Iterator> type;
-        };
-    };
-
-    template<>
-    struct traits_by_size<sizeof(random_access_iter_sizer)> {
-      template<typename Iterator>
-        struct traits {
-          typedef random_access_iterator_traits<Iterator> type;
-        };
-    };
-
-    template<typename Iterator>
-    class deduced_traits {
-      typedef typename ::boost::BOOST_ITERATOR_CATEGORY<Iterator>::type
-          category;
-
-      BOOST_STATIC_CONSTANT(
-          size_t, sizer_result = sizeof (sizer (new category)));
-
-    public:
-      typedef typename traits_by_size<sizer_result>
-        ::BOOST_NESTED_TEMPLATE traits<Iterator>::type type;
-    };
-  }
-
-  template<typename Iterator>
-  struct iterator_traits
-    : public iterator_detail::deduced_traits<Iterator>::type
-  {
-  };
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_ITERATOR_TRAITS_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/list.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/list.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/list.hpp	1970-01-01 00:00:00 +0000
@@ -1,168 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file list.hpp
-//
-// Indexing algorithms support for std::list instances
-//
-// History
-// =======
-// 2003/10/28   rmg     File creation from algo_selector.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: list.hpp,v 1.1.2.7 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_LIST_HPP
-#define BOOST_PYTHON_INDEXING_LIST_HPP
-
-#include <indexing_suite/container_traits.hpp>
-#include <indexing_suite/container_suite.hpp>
-#include <indexing_suite/algorithms.hpp>
-#include <list>
-
-#if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
-# include <boost/static_assert.hpp>
-# include <boost/type_traits.hpp>
-#endif
-
-namespace boost { namespace python { namespace indexing {
-  /////////////////////////////////////////////////////////////////////////
-  // ContainerTraits implementation for std::list instances
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename Container, typename ValueTraits = detail::no_override>
-  class list_traits
-    : public base_container_traits<Container, ValueTraits>
-  {
-    typedef base_container_traits<Container, ValueTraits> base_class;
-
-  public:
-    typedef typename base_class::value_traits_type value_traits_type;
-
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = (
-              method_len
-            | method_iter
-
-            | detail::method_set_if<
-                  value_traits_type::equality_comparable,
-                    method_contains
-                  | method_count
-              >::value
-
-            | detail::method_set_if<
-                  base_class::is_mutable,
-                  method_reverse
-                  | method_append
-              >::value
-
-            | detail::method_set_if<
-                  type_traits::ice_and<
-                      base_class::is_mutable,
-                      value_traits_type::less_than_comparable
-                  >::value,
-                  method_sort
-              >::value
-
-        ));
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Algorithms implementation for std::list instances
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr = detail::no_override>
-  class list_algorithms
-    : public default_algorithms
-        <ContainerTraits,
-        typename detail::maybe_override
-            <list_algorithms<ContainerTraits, Ovr>, Ovr>
-          ::type>
-  {
-    typedef list_algorithms<ContainerTraits, Ovr> self_type;
-    typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
-    typedef default_algorithms<ContainerTraits, most_derived> Parent;
-
-  public:
-    typedef typename Parent::container container;
-
-    // Use member functions for the following (hiding base class versions)
-    static void      reverse    (container &);
-    static void      sort       (container &);
-    //    static void      sort       (container &, PyObject *);
-  };
-
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  namespace detail {
-    ///////////////////////////////////////////////////////////////////////
-    // algorithms support for std::list instances
-    ///////////////////////////////////////////////////////////////////////
-
-    template <class T, class Allocator>
-    class algorithms_selector<std::list<T, Allocator> >
-    {
-      typedef std::list<T, Allocator> Container;
-
-      typedef list_traits<Container>       mutable_traits;
-      typedef list_traits<Container const> const_traits;
-
-    public:
-      typedef list_algorithms<mutable_traits> mutable_algorithms;
-      typedef list_algorithms<const_traits>   const_algorithms;
-    };
-  }
-#endif
-
-  template<
-    class Container,
-    method_set_type MethodMask = all_methods,
-    class Traits = list_traits<Container>
-  >
-  struct list_suite
-    : container_suite<Container, MethodMask, list_algorithms<Traits> >
-  {
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Reverse the contents of a list (using member function)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void list_algorithms<ContainerTraits, Ovr>::reverse (container &c)
-  {
-    c.reverse();
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Sort the contents of a list (using member function)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void list_algorithms<ContainerTraits, Ovr>::sort (container &c)
-  {
-    typedef typename self_type::container_traits::value_traits_type
-      vtraits;
-
-    typedef typename vtraits::less comparison;
-#if BOOST_WORKAROUND (BOOST_MSVC, == 1200)
-    // MSVC6 doesn't have a templated sort member in list, so we just
-    // use the parameterless version. This gives the correct behaviour
-    // provided that value_traits_type::less is exactly
-    // std::less<value_type>. It would be possible to support
-    // std::greater<T> (the only other overload of list::sort in
-    // MSVC6) with some additional work.
-    BOOST_STATIC_ASSERT(
-        (::boost::is_same<comparison, std::less<value_type> >::value));
-    c.sort ();
-#else
-    c.sort (comparison());
-#endif
-  }
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_LIST_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/map.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/map.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/map.hpp	1970-01-01 00:00:00 +0000
@@ -1,239 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file map.hpp
-//
-// Indexing algorithms support for std::map instances
-//
-// History
-// =======
-// 2003/10/28   rmg     File creation from algo_selector.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: map.hpp,v 1.1.2.6 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_MAP_HPP
-#define BOOST_PYTHON_INDEXING_MAP_HPP
-
-#include <indexing_suite/container_traits.hpp>
-#include <indexing_suite/container_suite.hpp>
-#include <indexing_suite/algorithms.hpp>
-#include <boost/detail/workaround.hpp>
-#include <map>
-#include <indexing_suite/pair.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  /////////////////////////////////////////////////////////////////////////
-  // ContainerTraits implementation for std::map instances
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename Container>
-  class map_traits : public base_container_traits<Container>
-  {
-    typedef base_container_traits<Container> base_class;
-
-  public:
-# if BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
-    // MSVC6 has a nonstandard name for mapped_type in std::map
-    typedef typename Container::referent_type value_type;
-# else
-    typedef typename Container::mapped_type value_type;
-# endif
-    typedef value_type &                    reference;
-    typedef typename Container::key_type    index_type; // operator[]
-    typedef typename Container::key_type    key_type;   // find, count, ...
-
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
-      value_param;
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
-      key_param;
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <index_type>::param_type
-      index_param;
-
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = (
-              method_iter
-
-            | method_getitem
-            | method_contains
-            | method_count
-            | method_has_key
-
-            | detail::method_set_if<
-                  base_class::is_mutable,
-                    method_setitem
-                  | method_delitem
-                  | method_insert
-              >::value
-        ));
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Algorithms implementation for std::map instances
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr = detail::no_override>
-  class map_algorithms
-    : public assoc_algorithms
-        <ContainerTraits,
-        typename detail::maybe_override
-            <map_algorithms<ContainerTraits, Ovr>, Ovr>
-          ::type>
-  {
-    typedef map_algorithms<ContainerTraits, Ovr> self_type;
-    typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
-    typedef assoc_algorithms<ContainerTraits, most_derived> Parent;
-
-  public:
-    typedef typename Parent::container container;
-    typedef typename Parent::reference reference;
-    typedef typename Parent::index_param index_param;
-    typedef typename Parent::value_param value_param;
-
-    static reference get (container &, index_param);
-    // Version to return only the mapped type
-
-    static boost::python::list keys( container & );
-
-    static void      assign     (container &, index_param, value_param);
-    static void      insert     (container &, index_param, value_param);
-
-    template<typename PythonClass, typename Policy>
-    static void visit_container_class( PythonClass &pyClass, Policy const &policy)
-    {
-      ContainerTraits::visit_container_class (pyClass, policy);
-      pyClass.def( "keys", &self_type::keys );
-
-      typedef BOOST_DEDUCED_TYPENAME most_derived::container::value_type value_type;
-      mapping::register_value_type< PythonClass, value_type, Policy >( pyClass );
-      //now we can expose iterators functionality
-      pyClass.def( "__iter__", python::iterator< BOOST_DEDUCED_TYPENAME most_derived::container >() );
-    }
-
-  };
-
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  namespace detail {
-    ///////////////////////////////////////////////////////////////////////
-    // algorithms support for std::map instances
-    ///////////////////////////////////////////////////////////////////////
-
-    template <class Key, class T, class Compare, class Allocator>
-    class algorithms_selector<std::map<Key, T, Compare, Allocator> >
-    {
-      typedef std::map<Key, T, Compare, Allocator> Container;
-
-      typedef map_traits<Container>       mutable_traits;
-      typedef map_traits<Container const> const_traits;
-
-    public:
-      typedef map_algorithms<mutable_traits> mutable_algorithms;
-      typedef map_algorithms<const_traits>   const_algorithms;
-    };
-
-    ///////////////////////////////////////////////////////////////////////
-    // algorithms support for std::multimap instances
-    ///////////////////////////////////////////////////////////////////////
-
-    template <class Key, class T, class Compare, class Allocator>
-    class algorithms_selector<std::multimap<Key, T, Compare, Allocator> >
-    {
-      typedef std::multimap<Key, T, Compare, Allocator> Container;
-
-      typedef map_traits<Container>       mutable_traits;
-      typedef map_traits<Container const> const_traits;
-
-    public:
-      typedef map_algorithms<mutable_traits> mutable_algorithms;
-      typedef map_algorithms<const_traits>   const_algorithms;
-    };
-  }
-#endif
-
-  template<
-    class Container,
-    method_set_type MethodMask = all_methods,
-    class Traits = map_traits<Container>
-  >
-  struct map_suite
-    : container_suite<Container, MethodMask, map_algorithms<Traits> >
-  {
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Index into a container (map version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  BOOST_DEDUCED_TYPENAME map_algorithms<ContainerTraits, Ovr>::reference
-  map_algorithms<ContainerTraits, Ovr>::get (container &c, index_param ix)
-  {
-    return most_derived::find_or_throw (c, ix)->second;
-  }
-
-
-  template<typename ContainerTraits, typename Ovr>
-  boost::python::list
-  map_algorithms<ContainerTraits, Ovr>::keys( container &c )
-  {
-    boost::python::list _keys;
-    //For some reason code with set could not be compiled
-    //std::set< key_param > unique_keys;
-    typedef BOOST_DEDUCED_TYPENAME container::iterator iter_type;
-    for( iter_type index = most_derived::begin(c); index != most_derived::end(c); ++index ){
-        //if( unique_keys.end() == unique_keys.find( index->first ) ){
-        //    unique_keys.insert( index->first );
-        if( !_keys.count( index->first ) ){
-            _keys.append( index->first );
-        }
-        //}
-    }
-
-    return _keys;
-  }
-
-  /////////////////////////////////////////////////////////////////////////
-  // Assign a value at a particular index (map version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  map_algorithms<ContainerTraits, Ovr>::assign(
-      container &c, index_param ix, value_param val)
-  {
-    c[ix] = val;   // Handles overwrite and insert
-  }
-
-
-  /////////////////////////////////////////////////////////////////////////
-  // Insert a new key, value pair into a map
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  map_algorithms<ContainerTraits, Ovr>::insert(
-      container &c, index_param ix, value_param val)
-  {
-    typedef std::pair
-      <BOOST_DEDUCED_TYPENAME self_type::container_traits::index_type,
-      BOOST_DEDUCED_TYPENAME self_type::container_traits::value_type>
-      pair_type;
-
-    // Can't use std::make_pair, because param types may be references
-
-    if (!c.insert (pair_type (ix, val)).second)
-      {
-        PyErr_SetString(
-            PyExc_ValueError, "Map already holds value for insertion");
-
-        boost::python::throw_error_already_set ();
-      }
-  }
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_MAP_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/methods.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/methods.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/methods.hpp	1970-01-01 00:00:00 +0000
@@ -1,114 +0,0 @@
-// Copyright (c) 2004 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file methods.hpp
-//
-// Methods (and sets of methods) that containers can provide.
-//
-// History
-// =======
-// 2004/ 1/11   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: methods.hpp,v 1.1.2.1 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_METHODS_HPP
-#define BOOST_PYTHON_INDEXING_METHODS_HPP
-
-#include <boost/config.hpp>
-#include <boost/mpl/if.hpp>
-
-namespace boost { namespace python { namespace indexing {
-
-  typedef unsigned long method_set_type;
-
-  enum methods_enum {
-    method_len            = 1UL <<  0,
-    method_iter           = 1UL <<  1,
-    method_getitem        = 1UL <<  2,
-    method_getitem_slice  = 1UL <<  3,
-    method_index          = 1UL <<  4,
-    method_contains       = 1UL <<  5,
-    method_count          = 1UL <<  6,
-    method_has_key        = 1UL <<  7,
-    method_setitem        = 1UL <<  8,
-    method_setitem_slice  = 1UL <<  9,
-    method_delitem        = 1UL << 10,
-    method_delitem_slice  = 1UL << 11,
-    method_reverse        = 1UL << 12,
-    method_append         = 1UL << 13,
-    method_insert         = 1UL << 14,
-    method_extend         = 1UL << 15,
-    method_sort           = 1UL << 16
-  };
-
-  // Some sets of methods that could be useful for disabling expensive
-  // features. e.g. something & ~(slice_methods | search_methods)
-
-  enum {
-    slice_methods
-      = method_getitem_slice | method_setitem_slice | method_delitem_slice
-  };
-
-  enum {
-    search_methods
-      = method_index | method_contains | method_count | method_has_key
-  };
-
-  enum {
-    reorder_methods
-      = method_sort | method_reverse
-  };
-
-  enum {
-    insert_methods
-      = method_append | method_insert | method_extend
-  };
-
-  enum {
-    all_methods = ~0UL
-  };
-
-  namespace detail {
-    // Compile-time constant selection:
-    //
-    // method_set_if<c, t, f>::value == (c ? t : f)
-    //
-    // where c is convertible to bool, and t and f are convertible to
-    // method_set_type. This gives a compile-time constant reliably on
-    // all supported compilers.
-
-    template<
-        bool Cond, method_set_type TrueValue, method_set_type FalseValue = 0>
-
-    struct method_set_if {
-      struct true_type {
-        BOOST_STATIC_CONSTANT(method_set_type, value = TrueValue);
-      };
-
-      struct false_type {
-        BOOST_STATIC_CONSTANT(method_set_type, value = FalseValue);
-      };
-
-      typedef typename mpl::if_c<Cond, true_type, false_type>::type
-          result_type;
-
-      BOOST_STATIC_CONSTANT(method_set_type, value = result_type::value);
-    };
-
-    // Compile-time set membership test:
-    // is_member<set, mem>::value == (bool) set & mem
-    template<method_set_type Set, method_set_type Member>
-    struct is_member {
-      // Use a cast to prevent MSVC truncation warning C4305
-      BOOST_STATIC_CONSTANT (bool, value = (bool) (Set & Member));
-    };
-  }
-
-} } } // boost::python::indexing
-
-#endif // BOOST_PYTHON_INDEXING_METHODS_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/multimap.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/multimap.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/multimap.hpp	1970-01-01 00:00:00 +0000
@@ -1,204 +0,0 @@
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file multimap.hpp
-//
-// Indexing algorithms support for std::multimap instances
-//
-// History
-// =======
-// 2006/10/27   Roman     File creation from map.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-
-#ifndef BOOST_PYTHON_INDEXING_MULTIMAP_HPP
-#define BOOST_PYTHON_INDEXING_MULTIMAP_HPP
-
-#include <indexing_suite/container_traits.hpp>
-#include <indexing_suite/container_suite.hpp>
-#include <indexing_suite/algorithms.hpp>
-#include <boost/detail/workaround.hpp>
-#include <functional>
-#include <map>
-#include <indexing_suite/pair.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  /////////////////////////////////////////////////////////////////////////
-  // ContainerTraits implementation for std::map instances
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename Container>
-  class multimap_traits : public base_container_traits<Container>
-  {
-    typedef base_container_traits<Container> base_class;
-
-  public:
-# if BOOST_WORKAROUND (BOOST_MSVC, <= 1200)
-    // MSVC6 has a nonstandard name for mapped_type in std::multimap
-    typedef typename Container::referent_type value_type;
-# else
-    typedef typename Container::mapped_type value_type;
-# endif
-    typedef value_type &                    reference;
-    typedef typename Container::key_type    index_type; // operator[]
-    typedef typename Container::key_type    key_type;   // find, count, ...
-
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
-      value_param;
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
-      key_param;
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <index_type>::param_type
-      index_param;
-
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = (
-              method_iter
-
-            | method_getitem
-            | method_contains
-            | method_count
-            | method_has_key
-
-            | detail::method_set_if<
-                  base_class::is_mutable,
-                    method_setitem
-                  | method_delitem
-                  | method_insert
-              >::value
-        ));
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Algorithms implementation for std::multimap instances
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr = detail::no_override>
-  class multimap_algorithms
-    : public assoc_algorithms
-        <ContainerTraits,
-        typename detail::maybe_override
-            <multimap_algorithms<ContainerTraits, Ovr>, Ovr>
-          ::type>
-  {
-    typedef multimap_algorithms<ContainerTraits, Ovr> self_type;
-    typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
-    typedef assoc_algorithms<ContainerTraits, most_derived> Parent;
-
-  public:
-    typedef typename Parent::container container;
-    typedef typename Parent::reference reference;
-    typedef typename Parent::index_param index_param;
-    typedef typename Parent::value_param value_param;
-
-    static boost::python::list get (container &, index_param);
-    // Version to return only the mapped type
-
-    static boost::python::list keys( container & );
-
-    static void      assign     (container &, index_param, value_param);
-    static void      insert     (container &, index_param, value_param);
-
-    template<typename PythonClass, typename Policy>
-    static void visit_container_class( PythonClass &pyClass, Policy const &policy)
-    {
-      ContainerTraits::visit_container_class (pyClass, policy);
-      pyClass.def( "keys", &self_type::keys );
-
-      typedef BOOST_DEDUCED_TYPENAME most_derived::container::value_type value_type;
-      mapping::register_value_type< PythonClass, value_type, Policy >( pyClass );
-      //now we can expose iterators functionality
-      pyClass.def( "__iter__", python::iterator< BOOST_DEDUCED_TYPENAME most_derived::container >() );
-
-    }
-
-  };
-
-  template<
-    class Container,
-    method_set_type MethodMask = all_methods,
-    class Traits = multimap_traits<Container>
-  >
-  struct multimap_suite
-    : container_suite<Container, MethodMask, multimap_algorithms<Traits> >
-  {
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Index into a container (multimap version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  boost::python::list
-  multimap_algorithms<ContainerTraits, Ovr>::get (container &c, index_param ix)
-  {
-    boost::python::list l;
-    typedef BOOST_DEDUCED_TYPENAME container::iterator iter_type;
-    for( iter_type index = c.lower_bound( ix ); index != c.upper_bound( ix ); ++index ){
-        boost::python::object v( index->second );
-        l.append( v );
-    }
-    return l;
-  }
-
-  template<typename ContainerTraits, typename Ovr>
-  boost::python::list
-  multimap_algorithms<ContainerTraits, Ovr>::keys( container &c )
-  {
-    boost::python::list _keys;
-    //For some reason code with set could not be compiled
-    //std::set< key_param > unique_keys;
-    typedef BOOST_DEDUCED_TYPENAME container::iterator iter_type;
-    for( iter_type index = most_derived::begin(c); index != most_derived::end(c); ++index ){
-        //if( unique_keys.end() == unique_keys.find( index->first ) ){
-        //    unique_keys.insert( index->first );
-        if( !_keys.count( index->first ) ){
-            _keys.append( index->first );
-        }
-        //}
-    }
-
-    return _keys;
-  }
-
-
-  /////////////////////////////////////////////////////////////////////////
-  // Assign a value at a particular index (map version)
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  multimap_algorithms<ContainerTraits, Ovr>::assign(
-      container &c, index_param ix, value_param val)
-  {
-    typedef std::pair<
-        BOOST_DEDUCED_TYPENAME self_type::container_traits::index_type
-        , BOOST_DEDUCED_TYPENAME self_type::container_traits::value_type>
-    pair_type;
-
-    // Can't use std::make_pair, because param types may be references
-    c.insert (pair_type (ix, val));
-  }
-
-
-  /////////////////////////////////////////////////////////////////////////
-  // Insert a new key, value pair into a map
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  multimap_algorithms<ContainerTraits, Ovr>::insert(
-      container &c, index_param ix, value_param val)
-  {
-    typedef std::pair
-      <BOOST_DEDUCED_TYPENAME self_type::container_traits::index_type,
-      BOOST_DEDUCED_TYPENAME self_type::container_traits::value_type>
-      pair_type;
-
-    // Can't use std::make_pair, because param types may be references
-    c.insert (pair_type (ix, val) );
-  }
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_MULTIMAP_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/pair.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/pair.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/pair.hpp	1970-01-01 00:00:00 +0000
@@ -1,99 +0,0 @@
-// Header file pair.hpp
-//
-// Exposes std::pair< key, value > class
-//
-// Copyright (c) 2007 Roman Yakovenko
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2007/2/11   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-
-#ifndef BOOST_PYTHON_STD_PAIR_KEY_VALUE_11_02_2007_HPP
-#define BOOST_PYTHON_STD_PAIR_KEY_VALUE_11_02_2007_HPP
-
-#include <boost/config.hpp>
-#include <indexing_suite/container_traits.hpp>
-#include <indexing_suite/container_suite.hpp>
-#include <indexing_suite/algorithms.hpp>
-#include <boost/detail/workaround.hpp>
-
-namespace boost { namespace python { namespace indexing { namespace mapping{
-
-namespace details{
-
-template< typename TValueType, typename TValueCallPolicies >
-struct pair_exposer_t{
-
-    typedef TValueType pair_type;
-    typedef BOOST_DEDUCED_TYPENAME pair_type::first_type key_type;
-    typedef BOOST_DEDUCED_TYPENAME pair_type::second_type mapped_type;
-    typedef pair_exposer_t< TValueType, TValueCallPolicies > exposer_type;
-
-    pair_exposer_t(const std::string& name){
-        class_< pair_type >( name.c_str() )
-            .def( "__len__", &exposer_type::len )
-            .def( "__getitem__", &exposer_type::get_item )
-            .add_property( "key", &exposer_type::get_key )
-            .add_property( "value", &exposer_type::get_mapped );
-    }
-
-private:
-
-    static size_t len( const pair_type& ){
-        return 2;
-    }
-
-    static object get_item( pair_type& p, size_t index ){
-        switch( index ){
-            case 0:{
-                return get_key( p );
-            }
-            case 1:{
-                return get_mapped( p );
-            }
-            case 2:{
-                objects::stop_iteration_error();
-                return object(); //will not reach this line
-            }
-            default:{
-                PyErr_SetString( PyExc_IndexError, "the only valid index numbers are: 0 and 1");
-                throw_error_already_set();
-                return object(); //will not reach this line
-            }
-        }
-    }
-
-    static object get_key( const pair_type& p ){
-        return object( p.first );
-    }
-
-    static object get_mapped( pair_type& p ){
-        typedef BOOST_DEDUCED_TYPENAME TValueCallPolicies::result_converter rc_type;
-        typedef BOOST_DEDUCED_TYPENAME rc_type:: template apply< mapped_type >::type converter_type;
-        converter_type converter;
-        return object( handle<>( converter( p.second ) ) );
-    }
-
-};
-} //details
-
-template< typename TPythonClass, typename TValueType, typename TValueCallPolicies >
-inline void register_value_type(TPythonClass &pyClass){
-    typedef details::pair_exposer_t< TValueType, TValueCallPolicies > exposer_type;
-
-    object class_name(pyClass.attr("__name__"));
-    extract<std::string> class_name_extractor(class_name);
-    std::string pair_name = class_name_extractor() + "_entry";
-
-    exposer_type expose( pair_name );
-}
-
-} } } }
-
-#endif // BOOST_PYTHON_STD_PAIR_KEY_VALUE_11_02_2007_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/proxy_iterator.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/proxy_iterator.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/proxy_iterator.hpp	1970-01-01 00:00:00 +0000
@@ -1,164 +0,0 @@
-
-// Header file proxy_iterator.hpp
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/10/ 8   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: proxy_iterator.hpp,v 1.1.2.8 2003/12/05 17:36:14 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_PROXY_ITERATOR_HPP
-#define BOOST_PYTHON_INDEXING_PROXY_ITERATOR_HPP
-
-#include <iterator>
-#include <boost/config.hpp>
-#include <boost/iterator.hpp>
-#include <boost/detail/workaround.hpp>
-
-namespace boost { namespace python { namespace indexing {
-
-  template <class ContainerProxy, typename ElementProxy, typename Traits,
-      typename Size, typename Iter>
-  class proxy_iterator
-    : public boost::iterator<
-          std::random_access_iterator_tag,
-          ElementProxy,
-          typename Traits::difference_type,
-          ElementProxy *,
-          ElementProxy // Already has reference semantics
-      >
-  {
-#if !defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
-    template<class C, class H, class G> friend class container_proxy;
-#endif
-
-    typedef boost::iterator<
-        std::random_access_iterator_tag,
-        ElementProxy,
-        typename Traits::difference_type,
-        ElementProxy *,
-        ElementProxy
-    > base_type;
-
-  public:
-    typedef ContainerProxy container_proxy_type;
-
-    typedef Iter raw_iterator;
-    typedef Traits raw_iterator_traits;
-    typedef Size size_type;
-    typedef typename base_type::value_type value_type;
-    typedef typename base_type::difference_type difference_type;
-
-    typedef value_type *pointer;
-    typedef value_type reference; // Already has reference semantics
-
-    proxy_iterator (container_proxy_type *p, size_type i)
-      : ptr (p), index (i)
-    {
-    }
-
-    proxy_iterator (container_proxy_type *p, raw_iterator iter)
-      : ptr (p), index (iter - p->raw_container().begin())
-    {
-    }
-
-    reference operator*() const { return ptr->at(index); }
-    pointer operator->() const { return &ptr->at(index); }
-    reference operator[](size_type s) { return ptr->at (index + s); }
-
-    proxy_iterator &operator++ () { ++index; return *this; }
-    proxy_iterator &operator+= (size_type s) { index += s; return *this; }
-
-    proxy_iterator &operator-- () { --index; return *this; }
-
-    proxy_iterator operator++ (int) {
-      proxy_iterator temp(*this);
-      ++index;
-      return temp;
-    }
-
-    proxy_iterator operator-- (int) {
-      proxy_iterator temp(*this);
-      --index;
-      return temp;
-    }
-
-    proxy_iterator &operator-= (size_type s) { index -= s; return *this; }
-
-    proxy_iterator operator+ (size_type s) const {
-      return proxy_iterator(*this) += s;
-    }
-
-    proxy_iterator operator- (size_type s) const {
-      return proxy_iterator(*this) -= s;
-    }
-
-    difference_type operator- (proxy_iterator i) const {
-      return index - i.index;
-    }
-
-    bool operator== (proxy_iterator const &other) const {
-      return (ptr == other.ptr) && (index == other.index);
-    }
-
-    bool operator!= (proxy_iterator const &other) const {
-      return !(*this == other);
-    }
-
-    bool operator< (proxy_iterator const &other) const {
-      return index < other.index;
-    }
-
-    bool operator<= (proxy_iterator const &other) const {
-      return index <= other.index;
-    }
-
-    bool operator> (proxy_iterator const &other) const {
-      return index > other.index;
-    }
-
-    bool operator>= (proxy_iterator const &other) const {
-      return index >= other.index;
-    }
-
-    void iter_swap (proxy_iterator const &other) const {
-      ptr->swap_elements (index, other.index);
-    }
-
-    //  public:
-    // Extensions to the normal iterator interface
-    //    void replace (value_type const &copy) { ptr->replace (index, copy); }
-
-#if defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
-    // Can't declare container_proxy as friend, so make data public
-  public:
-#else
-  private:
-#endif
-    container_proxy_type *ptr;
-    size_type index;
-  };
-} } }
-
-#if !BOOST_WORKAROUND (BOOST_MSVC, == 1300)
-// MSVC7.0 can't decide between this and the unspecialized version
-namespace std {
-  template <class C, typename E, typename T, typename S, typename I>
-  void iter_swap(
-      boost::python::indexing::proxy_iterator<C, E, T, S, I> const &first,
-      boost::python::indexing::proxy_iterator<C, E, T, S, I> const &second)
-  {
-    first.iter_swap (second);
-  }
-}
-#endif
-
-#endif // BOOST_PYTHON_INDEXING_PROXY_ITERATOR_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/python_iterator.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/python_iterator.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/python_iterator.hpp	1970-01-01 00:00:00 +0000
@@ -1,81 +0,0 @@
-// -*- mode:c++ -*-
-//
-// Header file python_iterator.hpp
-//
-// Handy Python iterable iterators
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/ 9/10   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: python_iterator.hpp,v 1.1.2.5 2003/11/24 16:35:09 raoulgough Exp $
-//
-// 2008 November 27 Roman Yakovenko
-// implementation of the member functions was moved from cpp to header.
-// this was done to simplify "installation" procedure.
-
-#ifndef BOOST_PYTHON_INDEXING_PYTHON_ITERATOR_HPP
-#define BOOST_PYTHON_INDEXING_PYTHON_ITERATOR_HPP
-
-#include <boost/python/object.hpp>
-#include <boost/python/handle.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  struct /*BOOST_PYTHON_DECL*/ python_iterator
-  {
-    python_iterator (boost::python::object obj)
-    : m_iter_obj (handle<> (PyObject_GetIter (obj.ptr()))),
-      m_next_method (m_iter_obj.attr ("next")),
-      m_current()
-    {
-    }
-
-    // Sets a python type exception and calls throw_error_already_set if
-    // the passed object is not iterable via PyObject_GetIter
-
-    bool next ()
-    {
-        bool result = true; // Assume success
-
-        try
-        {
-            m_current = m_next_method ();
-        }
-        catch (boost::python::error_already_set const &)
-        {
-            if (PyErr_ExceptionMatches (PyExc_StopIteration))
-            {
-                // Eat this exception
-                PyErr_Clear ();
-                m_current = boost::python::object (); // No current object
-                result = false; // Report failure via return value only
-            }
-            else
-            {
-                // Pass it up the line
-                throw;
-            }
-        }
-        return result;
-    }
-    // Get the next item from the iterator, returning true for success
-
-    boost::python::object current() const
-    { return m_current; }
-    // Callable only after a successful next()
-
-  private:
-    ::boost::python::object m_iter_obj;
-    ::boost::python::object m_next_method;
-    ::boost::python::object m_current;
-  };
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_PYTHON_ITERATOR_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/set.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/set.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/set.hpp	1970-01-01 00:00:00 +0000
@@ -1,168 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file set.hpp
-//
-// Indexing algorithms support for std::set instances
-//
-// History
-// =======
-// 2003/10/28   rmg     File creation from algo_selector.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: set.hpp,v 1.1.2.6 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_SET_HPP
-#define BOOST_PYTHON_INDEXING_SET_HPP
-
-#include <indexing_suite/container_traits.hpp>
-#include <indexing_suite/container_suite.hpp>
-#include <indexing_suite/algorithms.hpp>
-#include <boost/type_traits/is_const.hpp>
-#include <set>
-
-namespace boost { namespace python { namespace indexing {
-  /////////////////////////////////////////////////////////////////////////
-  // ContainerTraits implementation for std::set instances
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename Container>
-  class set_traits : public base_container_traits<Container>
-  {
-    typedef base_container_traits<Container> base_class;
-
-  public:
-    typedef typename Container::key_type value_type; // probably unused
-    typedef typename Container::key_type index_type; // operator[]
-    typedef typename Container::key_type key_type;   // find, count, ...
-
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <value_type>::param_type
-        value_param;
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <key_type>::param_type
-        key_param;
-    typedef typename BOOST_PYTHON_INDEXING_CALL_TRAITS <index_type>::param_type
-        index_param;
-
-    BOOST_STATIC_CONSTANT(
-        method_set_type,
-        supported_methods = (
-              method_iter
-            | method_getitem
-            | method_contains
-            | method_count
-            | method_has_key
-
-            | detail::method_set_if<
-                  base_class::is_mutable,
-                    method_delitem
-                  | method_insert
-              >::value
-        ));
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Algorithms implementation for std::set instances
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr = detail::no_override>
-  class set_algorithms
-    : public assoc_algorithms
-        <ContainerTraits,
-        typename detail::maybe_override
-            <set_algorithms<ContainerTraits, Ovr>, Ovr>
-          ::type>
-  {
-    typedef set_algorithms<ContainerTraits, Ovr> self_type;
-    typedef typename detail::maybe_override<self_type, Ovr>::type most_derived;
-    typedef assoc_algorithms<ContainerTraits, most_derived> Parent;
-
-  public:
-    typedef typename Parent::container container;
-    typedef typename Parent::value_param value_param;
-    typedef typename Parent::index_param index_param;
-
-    static void      insert     (container &, index_param);
-
-    template<typename PythonClass, typename Policy>
-    static void visit_container_class( PythonClass &pyClass, Policy const &policy)
-    {
-      ContainerTraits::visit_container_class (pyClass, policy);
-      pyClass.def( "add", &self_type::insert );
-    }
-
-  };
-
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  namespace detail {
-    ///////////////////////////////////////////////////////////////////////
-    // algorithms support for std::set instances
-    ///////////////////////////////////////////////////////////////////////
-
-    template <class Key, class Compare, class Allocator>
-    class algorithms_selector<std::set<Key, Compare, Allocator> >
-    {
-      typedef std::set<Key, Compare, Allocator> Container;
-
-      typedef set_traits<Container>       mutable_traits;
-      typedef set_traits<Container const> const_traits;
-
-    public:
-      typedef set_algorithms<mutable_traits> mutable_algorithms;
-      typedef set_algorithms<const_traits>   const_algorithms;
-    };
-
-    ///////////////////////////////////////////////////////////////////////
-    // algorithms support for std::multiset instances
-    ///////////////////////////////////////////////////////////////////////
-
-    template <class Key, class Compare, class Allocator>
-    class algorithms_selector<std::multiset<Key, Compare, Allocator> >
-    {
-      typedef std::multiset<Key, Compare, Allocator> Container;
-
-      typedef set_traits<Container>       mutable_traits;
-      typedef set_traits<Container const> const_traits;
-
-    public:
-      typedef set_algorithms<mutable_traits> mutable_algorithms;
-      typedef set_algorithms<const_traits>   const_algorithms;
-    };
-  }
-#endif
-
-  template<
-    class Container,
-    method_set_type MethodMask = all_methods,
-    class Traits = set_traits<Container>
-  >
-  struct set_suite
-    : container_suite<Container, MethodMask, set_algorithms<Traits> >
-  {
-  };
-
-  /////////////////////////////////////////////////////////////////////////
-  // Insert an element into a set
-  /////////////////////////////////////////////////////////////////////////
-
-  template<typename ContainerTraits, typename Ovr>
-  void
-  set_algorithms<ContainerTraits, Ovr>::insert(
-      container &c, index_param ix)
-  {
-    c.insert (ix);
-    //~ Python set does not raise exception in this situation
-    //~ if (!c.insert (ix).second)
-      //~ {
-        //~ PyErr_SetString(
-            //~ PyExc_ValueError, "Set already holds value for insertion");
-
-        //~ boost::python::throw_error_already_set ();
-      //~ }
-  }
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_SET_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/shared_proxy_impl.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/shared_proxy_impl.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/shared_proxy_impl.hpp	1970-01-01 00:00:00 +0000
@@ -1,106 +0,0 @@
-//
-// Header file shared_proxy_impl.hpp
-//
-// The shared implementation of the element proxy (const and non-const
-// versions).  Multiple proxy pointers can refer to the same shared
-// implementation, meaning that only one object requires updating to
-// affect all proxy pointers that ultimately refer to the same index
-// in the container.
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/ 8/29   rmg     File creation from container_proxy.hh
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: shared_proxy_impl.hpp,v 1.1.2.8 2003/11/24 14:28:31 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_SHARED_PROXY_IMPL_HPP
-#define BOOST_PYTHON_INDEXING_SHARED_PROXY_IMPL_HPP
-
-#include <memory>
-#include <indexing_suite/workaround.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  template<class ContainerProxy>
-  class shared_proxy_impl
-  {
-  public:
-    typedef typename ContainerProxy::raw_value_type value_type;
-    typedef value_type &reference;
-    typedef value_type *pointer;
-    typedef void iterator_category;  // Fudge for boost::indirect_iterator
-    typedef void difference_type;    // Fudge for boost::indirect_iterator
-
-    reference operator*() const;
-    pointer operator->() const { return &(**this); }
-
-    ContainerProxy *owner() const { return m_owner_ptr; }
-    size_t index() const { return m_index; }
-
-    shared_proxy_impl (value_type const &copy);
-    // Creates value-only (detached) proxy
-
-#if defined (BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
-  public:
-#else
-  private:
-    template<class C, class A, class G> friend class container_proxy;
-#endif
-
-    shared_proxy_impl (ContainerProxy *, size_t);
-    void detach ();
-
-    ContainerProxy *m_owner_ptr;             // When attached
-    size_t m_index;                          // When attached
-    std::auto_ptr<value_type> m_element_ptr; // When detached
-
-  private:
-    // Not implemented
-    shared_proxy_impl (shared_proxy_impl const &);
-    shared_proxy_impl &operator= (shared_proxy_impl const &);
-  };
-
-  template<class ContainerProxy>
-  shared_proxy_impl<ContainerProxy>::shared_proxy_impl (ContainerProxy *owner,
-                                                        size_t index)
-    : m_owner_ptr (owner),
-    m_index (index),
-    m_element_ptr ()
-  {
-  }
-
-  template<class ContainerProxy>
-  shared_proxy_impl<ContainerProxy>::shared_proxy_impl (value_type const &val)
-    : m_owner_ptr (0),
-    m_index (static_cast<size_t>(-1)),
-    m_element_ptr (new value_type (val))
-  {
-  }
-
-  template<class ContainerProxy>
-  typename shared_proxy_impl<ContainerProxy>::reference
-  shared_proxy_impl<ContainerProxy>::operator* () const
-  {
-    return m_owner_ptr
-      ? m_owner_ptr->raw_container().BOOST_PYTHON_INDEXING_AT (m_index)
-      : *m_element_ptr;
-  }
-
-  template<class ContainerProxy>
-  void shared_proxy_impl<ContainerProxy>::detach ()
-  {
-    BOOST_PYTHON_INDEXING_RESET_AUTO_PTR(
-        m_element_ptr, new value_type (**this));
-    m_owner_ptr = 0;
-    m_index = static_cast<size_t>(-1);
-  }
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_SHARED_PROXY_IMPL_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/slice.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/slice.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/slice.hpp	1970-01-01 00:00:00 +0000
@@ -1,143 +0,0 @@
-// Header file slice.hpp
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/ 9/10   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: slice.hpp,v 1.1.2.10 2003/11/24 14:28:31 raoulgough Exp $
-//
-// 2008 November 27 Roman Yakovenko
-// implementation of the member functions was moved from cpp to header.
-// this was done to simplify "installation" procedure.
-
-#ifndef BOOST_PYTHON_INDEXING_SLICE_HPP
-#define BOOST_PYTHON_INDEXING_SLICE_HPP
-
-#include <boost/python/object.hpp>
-#include <boost/python/errors.hpp>
-#include <boost/python/converter/pytype_object_mgr_traits.hpp>
-#include <algorithm>
-
-namespace boost { namespace python { namespace indexing {
-  struct /*BOOST_PYTHON_DECL*/ slice : public boost::python::object
-  {
-    // This is just a thin wrapper around boost::python::object
-    // so that it is possible to register a special converter for
-    // PySlice_Type and overload C++ functions on slice
-
-#if defined (BOOST_NO_MEMBER_TEMPLATES)
-    // MSVC6 doesn't seem to be able to invoke the templated
-    // constructor, so provide explicit overloads to match the
-    // (currently) known boost::python::object constructors
-    explicit slice (::boost::python::handle<> const& p)
-    : object (p)
-    {}
-
-    explicit slice (::boost::python::detail::borrowed_reference p)
-    : object (p)
-    {}
-
-    explicit slice (::boost::python::detail::new_reference p)
-    : object (p)
-    {}
-
-    explicit slice (::boost::python::detail::new_non_null_reference p)
-    : object (p)
-    {}
-#else
-    // Better compilers make life easier
-    template<typename T> inline slice (T const &ref);
-#endif
-
-    slice (slice const & copy) // Copy constructor
-    : object (copy)
-    {}
-  };
-
-  struct /*BOOST_PYTHON_DECL*/ integer_slice
-  {
-    // This class provides a convenient interface to Python slice
-    // objects that contain integer bound and stride values.
-
-    #if PY_VERSION_HEX < 0x02050000
-        typedef int index_type;
-    #else
-        typedef Py_ssize_t index_type;
-    #endif
-
-    integer_slice (slice const & sl, index_type length)
-      : m_slice (sl) // Leave index members uninitialized
-    {
-        PySlice_GetIndices(
-            reinterpret_cast<PySliceObject *> (m_slice.ptr()),
-            length,
-            &m_start,
-            &m_stop,
-            &m_step);
-
-        if (m_step == 0)
-        {
-            // Can happen with Python prior to 2.3
-            PyErr_SetString (PyExc_ValueError, "slice step cannot be zero");
-            boost::python::throw_error_already_set ();
-        }
-
-        m_start = std::max (static_cast<index_type> (0), std::min (length, m_start));
-        m_stop = std::max (static_cast<index_type> (0), std::min (length, m_stop));
-        m_direction = (m_step > 0) ? 1 : -1;
-    }
-
-    // integer_slice must know how big the container is so it can
-    // adjust for negative indexes, etc...
-
-    index_type start() const { return m_start; }
-    index_type step() const  { return m_step; }
-    index_type stop() const  { return m_stop; }
-
-    index_type size() const { return (m_stop - m_start) / m_step; }
-
-    bool in_range (index_type index)
-    { return ((m_stop - index) * m_direction) > 0; }
-
-  private:
-    slice m_slice;
-    index_type m_start;
-    index_type m_step;
-    index_type m_stop;
-    index_type m_direction;
-  };
-} } }
-
-#if !defined (BOOST_NO_MEMBER_TEMPLATES)
-template<typename T>
-boost::python::indexing::slice::slice (T const &ref)
-  : boost::python::object (ref)
-{
-  if (!PySlice_Check (this->ptr()))
-    {
-      PyErr_SetString(
-          PyExc_TypeError, "slice constructor: passed a non-slice object");
-
-      boost::python::throw_error_already_set();
-    }
-}
-#endif
-
-namespace boost { namespace python { namespace converter {
-  // Specialized converter to handle PySlice_Type objects
-  template<>
-  struct object_manager_traits<boost::python::indexing::slice>
-    : pytype_object_manager_traits<
-         &PySlice_Type, ::boost::python::indexing::slice>
-  {
-  };
-}}}
-
-#endif // BOOST_PYTHON_INDEXING_SLICE_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/slice_handler.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/slice_handler.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/slice_handler.hpp	1970-01-01 00:00:00 +0000
@@ -1,302 +0,0 @@
-// -*- mode:c++ -*-
-//
-// Header file slice_handler.hpp
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/ 9/ 9   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-// 2009/01/30   Roman   patch from Maik Beckmann was applied - fixes error:
-//                      // error: no class template named 'extract_return_type'
-// $Id: slice_handler.hpp,v 1.1.2.10 2003/11/24 16:35:52 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_SLICE_HANDLER_HPP
-#define BOOST_PYTHON_INDEXING_SLICE_HANDLER_HPP
-
-#include <boost/python/handle.hpp>
-#include <boost/python/object.hpp>
-#include <boost/python/list.hpp>
-#include <boost/python/extract.hpp>
-#include <boost/python/make_function.hpp>
-#include <boost/mpl/apply.hpp>
-#include <algorithm>
-
-#include <indexing_suite/slice.hpp>
-#include <indexing_suite/python_iterator.hpp>
-
-namespace boost { namespace python { namespace indexing {
-  template<class Algorithms, class Policy>
-  struct slice_handler
-  {
-    static boost::python::object make_getitem (Policy const &);
-    static boost::python::object make_setitem (Policy const &);
-    static boost::python::object make_delitem (Policy const &);
-    static boost::python::object make_extend  (Policy const &);
-
-  private:
-    typedef typename Algorithms::container container;
-    typedef typename Algorithms::reference reference;
-    typedef typename Algorithms::slice_helper slice_helper;
-
-    static boost::python::list get_slice (container &, slice);
-    static void set_slice (container &, slice, boost::python::object);
-    static void del_slice (container &, slice);
-    static void extend (container &, boost::python::object);
-  };
-
-  namespace detail {
-    template<typename Policy>
-    struct postcall_override
-    {
-      // This class overrides the Policy's postcall function and
-      // result_conveter to handle the list returned from get_slice.
-      // The Policy's result_converter is removed, since it gets
-      // applied within get_slice. Our postcall override applies the
-      // original postcall to each element of the Python list returned
-      // from get_slice.
-
-      typedef boost::python::default_result_converter result_converter;
-      typedef typename Policy::argument_package argument_package;
-
-      template<class Sig> struct extract_return_type : 
-      Policy::template extract_return_type<Sig> { };
-
-      postcall_override (Policy const &p);
-
-      bool precall (PyObject *args);
-      PyObject* postcall (PyObject *args, PyObject *result);
-
-    private:
-      Policy m_base;
-    };
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // Return a function object that implements the slice version of __getitem__
-  //////////////////////////////////////////////////////////////////////////
-
-  template<class Algorithms, class Policy>
-  boost::python::object
-  slice_handler<Algorithms, Policy>
-  ::make_getitem (Policy const &policy)
-  {
-    return
-      boost::python::make_function(
-          get_slice, detail::postcall_override<Policy> (policy));
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // Return a function object that implements the slice version of __setitem__
-  //////////////////////////////////////////////////////////////////////////
-
-  template<class Algorithms, class Policy>
-  boost::python::object
-  slice_handler<Algorithms, Policy>
-  ::make_setitem (Policy const &policy)
-  {
-    // should we try to get funky with policy::precall?
-    return boost::python::make_function (set_slice, policy);
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // Return a function object that implements the slice version of __delitem__
-  //////////////////////////////////////////////////////////////////////////
-
-  template<class Algorithms, class Policy>
-  boost::python::object
-  slice_handler<Algorithms, Policy>
-  ::make_delitem (Policy const &policy)
-  {
-    // should we try to get funky with policy::precall?
-    return boost::python::make_function (del_slice, policy);
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // Return a function object that implements extend
-  //////////////////////////////////////////////////////////////////////////
-
-  template<class Algorithms, class Policy>
-  boost::python::object
-  slice_handler<Algorithms, Policy>
-  ::make_extend (Policy const &policy)
-  {
-    // should we try to get funky with policy::precall?
-    return boost::python::make_function (extend, policy);
-  }
-
-  namespace detail {
-    ////////////////////////////////////////////////////////////////////////
-    // postcall_override constructor
-    ////////////////////////////////////////////////////////////////////////
-
-    template<class Policy>
-    postcall_override<Policy>::postcall_override (Policy const &p)
-      : m_base (p)
-    {
-    }
-
-    ////////////////////////////////////////////////////////////////////////
-    // precall forwarder
-    ////////////////////////////////////////////////////////////////////////
-
-    template<class Policy>
-    bool postcall_override<Policy>::precall (PyObject *args)
-    {
-      return m_base.precall (args);
-    }
-
-    ////////////////////////////////////////////////////////////////////////
-    // Apply base postcall to each element of the list returend by get_slice
-    ////////////////////////////////////////////////////////////////////////
-
-    template<class Policy>
-    PyObject *
-    postcall_override<Policy>::postcall (PyObject *args, PyObject *result)
-    {
-      int size = PyList_Size (result);
-
-      for (int count = 0; count < size; ++count)
-        {
-          m_base.postcall (args, PyList_GetItem (result, count));
-        }
-
-      return result;
-    }
-  } // namespace detail
-
-  //////////////////////////////////////////////////////////////////////////
-  // Implementation for the slice version of __getitem__
-  //////////////////////////////////////////////////////////////////////////
-
-  template<class Algorithms, class Policy>
-  boost::python::list
-  slice_handler<Algorithms, Policy>
-  ::get_slice (container &c, slice sl)
-  {
-    typedef typename Policy::result_converter converter_type;
-    typedef typename Algorithms::reference reference;
-
-    typename boost::mpl::apply1<converter_type, reference>::type
-      converter;
-
-    boost::python::list result;
-
-    slice_helper helper (Algorithms::make_slice_helper (c, sl));
-
-    while (helper.next())
-      {
-        // Apply the result converter (only) to each element before
-        // appending. postcall is done in postcall_override
-
-        result.append (boost::python::handle<> (converter (helper.current())));
-      }
-
-    return result;
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // Implementation for the slice version of __setitem__
-  //////////////////////////////////////////////////////////////////////////
-
-  template<class Algorithms, class Policy>
-  void
-  slice_handler<Algorithms, Policy>
-  ::set_slice (container &c, slice sl, boost::python::object values)
-  {
-    python_iterator value_iter (values);
-
-    // Try two kinds of extractors - the first is more efficient (using
-    // a reference to existing object, if possible and sensible) and the
-    // second allowing implicit conversions.
-
-    typedef boost::python::extract<
-        BOOST_DEDUCED_TYPENAME Algorithms::value_param> extractor1;
-
-    typedef boost::python::extract<
-        BOOST_DEDUCED_TYPENAME Algorithms::value_type> extractor2;
-
-    // Note: any error during this operation will probably leave the
-    // container partially updated. This can occur (for example) if the
-    // replacement sequence is of a different length to the original
-    // slice and the container does not support insertion/deletion.
-    // This could be prevented if the length of the replacement sequence
-    // is known in advance (via __len__, for example) but not otherwise.
-
-    slice_helper write_helper (Algorithms::make_slice_helper (c, sl));
-
-    // Overwrite and/or insert elements
-    while (value_iter.next())
-      {
-        extractor1 ex1 (value_iter.current());
-
-        if (ex1.check())
-          {
-            write_helper.write (ex1);
-          }
-
-        else
-          {
-            write_helper.write (extractor2 (value_iter.current()));
-          }
-      }
-
-    if (write_helper.next())
-      {
-        // We've run out of elements to read, but write_helper is not
-        // finished. Erase the remaining element(s) in the slice
-        write_helper.erase_remaining();
-      }
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // Implementation for the slice version of __delitem__
-  //////////////////////////////////////////////////////////////////////////
-
-  template<class Algorithms, class Policy>
-  void
-  slice_handler<Algorithms, Policy>
-  ::del_slice (container &c, slice sl)
-  {
-    slice_helper helper (Algorithms::make_slice_helper (c, sl));
-
-    if (helper.next())
-      {
-        helper.erase_remaining();
-      }
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // Implementation of extend
-  //////////////////////////////////////////////////////////////////////////
-
-  template<class Algorithms, class Policy>
-  void
-  slice_handler<Algorithms, Policy>
-  ::extend (container &c, boost::python::object values)
-  {
-    // Set up a slice at the tail end of the container, and use
-    // set_slice to do all the hard work.
-
-    boost::python::object length
-      ((boost::python::handle<>
-        (PyInt_FromLong (Algorithms::size (c)))));
-
-    slice sl
-      ((boost::python::handle<>
-        (PySlice_New
-         (length.ptr(),
-          boost::python::object().ptr(),
-          boost::python::object().ptr()))));
-
-    set_slice (c, sl, values);
-  }
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_SLICE_HANDLER_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/suite_utils.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/suite_utils.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/suite_utils.hpp	1970-01-01 00:00:00 +0000
@@ -1,111 +0,0 @@
-// Header file suite_utils.hpp
-//
-// Shared utilities for the indexing suite.
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/ 8/23   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: suite_utils.hpp,v 1.1.2.7 2003/11/24 14:28:31 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_SUITE_UTILS_HPP
-#define BOOST_PYTHON_INDEXING_SUITE_UTILS_HPP
-
-#include <boost/type_traits.hpp>
-
-namespace boost { namespace python { namespace indexing {
-#if BOOST_WORKAROUND (BOOST_MSVC, BOOST_TESTED_AT (1310)) \
-  || (defined (__GNUC__) && (__GNUC__ < 3))
-  // MSVC and GCC 2.96 seem to have problems comparing enumerated
-  // values in a static constant expression, and don't believe that an
-  // expression like (traits::index_style >= index_style_nonlinear) is
-  // a compile-time constant. However, the problem doesn't exist for
-  // int.
-  typedef int index_style_t;
-  index_style_t const index_style_none = 0;
-  index_style_t const index_style_nonlinear = 1;
-  index_style_t const index_style_linear = 2;
-#else
-  enum index_style_t {
-    index_style_none,         // No random access (iteration only)
-    index_style_nonlinear,  // Random access by key (no slicing)
-    index_style_linear     // Random access by integer index (allows slicing)
-  };
-#endif
-
-  template<typename T>
-  class is_mutable_ref
-  {
-    typedef typename boost::remove_reference<T>::type maybe_const;
-
-  public:
-    BOOST_STATIC_CONSTANT (bool, value = !boost::is_const<maybe_const>::value);
-  };
-
-  // make_signed attempts to identify the signed version of any
-  // numeric type (useful in this case because Python container
-  // indexes can be negative).
-  template<typename T> struct make_signed {
-    typedef T type;
-  };
-
-  template<> struct make_signed<char> {
-    // Raw "char" could be signed or unsigned. "signed char"
-    // guarantess signedness
-    typedef signed char type;
-  };
-
-  template<> struct make_signed<unsigned char> {
-    typedef signed char type;
-  };
-
-  template<> struct make_signed<unsigned short> {
-    typedef short type;
-  };
-
-  template<> struct make_signed<unsigned int> {
-    typedef int type;
-  };
-
-  template<> struct make_signed<unsigned long> {
-    typedef long type;
-  };
-
-#if defined (BOOST_HAS_LONG_LONG)
-  template<> struct make_signed<unsigned long long> {
-    typedef long long type;
-  };
-#elif defined (BOOST_HAS_MS_INT64)
-  template<> struct make_signed<unsigned __int64> {
-    typedef __int64 type;
-  };
-#endif
-
-  namespace detail {
-    struct no_override { };
-
-    template<typename Base, typename Override>
-    struct maybe_override
-    {
-      // Probably need to disable this if there is no partial
-      // specialization support, because Override is almost certain to
-      // be an incomplete type. If that is right, the workaround
-      // version would just have to do "typedef Base type;"
-
-      typedef typename mpl::if_
-        <is_same <Override, no_override>, Base, Override>
-        ::type type;
-    };
-  }
-
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_SUITE_UTILS_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/value_traits.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/value_traits.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/value_traits.hpp	1970-01-01 00:00:00 +0000
@@ -1,85 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file value_traits.hpp:
-//
-// Traits information for use in determining which Python methods to
-// support for a container with elements of a given type.
-//
-// History
-// =======
-// 2003/ 9/12   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: value_traits.hpp,v 1.1.2.6 2003/12/05 17:36:12 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_VALUE_TRAITS_HPP
-#define BOOST_PYTHON_INDEXING_VALUE_TRAITS_HPP
-
-#include <boost/config.hpp>
-#include <boost/shared_ptr.hpp>
-#include <functional>
-
-namespace boost { namespace python { namespace indexing {
-  // The default_value_traits template is used by all ContainerTraits
-  // templates. It can be overridden by specialization or by supplying
-  // the optional ValueTraits parameter to a container traits
-  // template.
-  template<typename T> struct value_traits;
-
-  // Implementation for default use. Providing this in a separate
-  // template allows specializations of value_traits to make use of
-  // it.
-  template<typename T>
-  struct simple_value_traits {
-    BOOST_STATIC_CONSTANT (bool, equality_comparable = true);
-    typedef std::equal_to<T> equal_to;
-
-    BOOST_STATIC_CONSTANT (bool, less_than_comparable = true);
-    typedef std::less<T> less;
-
-    // Default, do-nothing, version of visit_container_class
-    template<typename PythonClass, typename Policy>
-    static void visit_container_class (PythonClass &, Policy const &) { }
-  };
-
-  // Implementation using pointer indirection
-  template <typename Ptr>
-  struct indirect_value_traits : simple_value_traits<Ptr> {
-    // Hide the base class versions of the comparisons, using these
-    // indirect versions
-    struct less : std::binary_function<Ptr, Ptr, bool> {
-      bool operator() (Ptr const &p1, Ptr const &p2) const {
-        return *p1 < *p2;
-      }
-    };
-
-    struct equal_to : std::binary_function<Ptr, Ptr, bool> {
-      bool operator() (Ptr const &p1, Ptr const &p2) const {
-        return *p1 == *p2;
-      }
-    };
-  };
-
-  // Default implementation selection. It's basically just a typedef
-  // for simple_value_traits
-  template<typename T>
-  struct value_traits : simple_value_traits<T>
-  {
-  };
-
-#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  // Partial specialization for instances of boost::shared_ptr
-  template<typename T>
-  struct value_traits< ::boost::shared_ptr<T> >
-    : indirect_value_traits< ::boost::shared_ptr<T> >
-  {
-  };
-#endif
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_VALUE_TRAITS_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/vector.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/vector.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/vector.hpp	1970-01-01 00:00:00 +0000
@@ -1,61 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file vector.hpp
-//
-// Indexing algorithms support for std::vector instances
-//
-// History
-// =======
-// 2003/10/28   rmg     File creation from algo_selector.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: vector.hpp,v 1.1.2.6 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_VECTOR_HPP
-#define BOOST_PYTHON_INDEXING_VECTOR_HPP
-
-#include <indexing_suite/container_traits.hpp>
-#include <indexing_suite/container_suite.hpp>
-#include <indexing_suite/algorithms.hpp>
-#include <vector>
-
-namespace boost { namespace python { namespace indexing {
-#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
-  namespace detail {
-    ///////////////////////////////////////////////////////////////////////
-    // algorithms support for std::vector instances
-    ///////////////////////////////////////////////////////////////////////
-
-    template <class T, class Allocator>
-    class algorithms_selector<std::vector<T, Allocator> >
-    {
-      typedef std::vector<T, Allocator> Container;
-
-      typedef random_access_sequence_traits<Container>       mutable_traits;
-      typedef random_access_sequence_traits<Container const> const_traits;
-
-    public:
-      typedef default_algorithms<mutable_traits> mutable_algorithms;
-      typedef default_algorithms<const_traits>   const_algorithms;
-    };
-  }
-#endif
-
-  template<
-    class Container,
-    method_set_type MethodMask = all_methods,
-    class Traits = random_access_sequence_traits<Container>
-  >
-  struct vector_suite
-    : container_suite<Container, MethodMask, default_algorithms<Traits> >
-  {
-  };
-
-} } }
-
-#endif // BOOST_PYTHON_INDEXING_VECTOR_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/visitor.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/visitor.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/visitor.hpp	1970-01-01 00:00:00 +0000
@@ -1,272 +0,0 @@
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// Header file visitor.hpp:
-//
-// def_visitor implementation to install the container_suite's Python
-// methods in an object of a boost::python::class_<> instance.
-//
-// History
-// =======
-// 2003/ 9/11   rmg     File creation from container_suite.hpp
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: visitor.hpp,v 1.1.2.16 2004/02/08 18:57:42 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_VISITOR_HPP
-#define BOOST_PYTHON_INDEXING_VISITOR_HPP
-
-#include <indexing_suite/slice_handler.hpp>
-#include <indexing_suite/suite_utils.hpp> // Get index_style_t
-
-#include <boost/python/def_visitor.hpp>
-#include <boost/python/iterator.hpp>
-#include <boost/python/default_call_policies.hpp>
-#include <boost/type_traits/ice.hpp>
-#include <boost/bind.hpp>
-#include <functional>
-
-namespace boost { namespace python { namespace indexing {
-  //////////////////////////////////////////////////////////////////////////
-  // Policy override template that masks everything except the precall
-  // functions. i.e. it uses default policies for everything except
-  // precall, which must be provided by the template argument.
-  //////////////////////////////////////////////////////////////////////////
-
-  namespace detail {
-    template<typename PrecallPolicy>
-    struct precall_only : public boost::python::default_call_policies
-    {
-      precall_only () : m_precall () { }
-      explicit precall_only (PrecallPolicy const &copy) : m_precall (copy) { }
-
-      bool precall (PyObject *args) { return m_precall.precall (args); }
-      bool precall (PyObject *args) const { return m_precall.precall (args); }
-
-    private:
-      PrecallPolicy m_precall;
-    };
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // Ugly macro to define a template that optionally adds a method to
-  // a Python class. This version (OPTIONAL_ALGO_SUPPORT) works with
-  // static functions in an Algorithms class.
-  //
-  // This macro is #undef'd at the end of this header
-  //////////////////////////////////////////////////////////////////////////
-
-#define OPTIONAL_ALGO_SUPPORT(ADDER_NAME, METHOD_NAME, ALGO_FN) \
-  template<bool doit>  \
-  struct ADDER_NAME {  \
-    template<class PythonClass, class Algorithms, class Policy>  \
-    static void apply (PythonClass &, Algorithms const &, Policy const &)  \
-    {  \
-    }  \
-  };  \
-\
-  template<>  \
-  struct ADDER_NAME<true> {  \
-    template<class PythonClass, class Algorithms, class Policy>  \
-    static void apply(  \
-        PythonClass &pyClass,  \
-        Algorithms const &,  \
-        Policy const &policy)  \
-    {  \
-      pyClass.def (METHOD_NAME, &Algorithms::ALGO_FN, policy);  \
-    }  \
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // Ugly macro to define a template that optionally adds a method to
-  // a Python class. This version (OPTIONAL_SLICE_SUPPORT) works with
-  // static functions in the slice_handler template.
-  //
-  // This macro is #undef'd at the end of this header
-  //////////////////////////////////////////////////////////////////////////
-
-#define OPTIONAL_SLICE_SUPPORT(ADDER_NAME, METHOD_NAME, SLICE_HANDLER_FN) \
-  template<bool doit>  \
-  struct ADDER_NAME {  \
-    template<class PythonClass, class Algorithms, class Policy>  \
-    static void apply (PythonClass &, Algorithms const &, Policy const &)  \
-    {  \
-    }  \
-  };  \
-\
-  template<>  \
-  struct ADDER_NAME<true> {  \
-    template<class PythonClass, class Algorithms, class Policy>  \
-    static void apply(  \
-        PythonClass &pyClass,  \
-        Algorithms const &,  \
-        Policy const &policy)  \
-    {  \
-      pyClass.def ( \
-          METHOD_NAME, \
-          slice_handler<Algorithms, Policy>::SLICE_HANDLER_FN (policy));  \
-    }  \
-  }
-
-  //////////////////////////////////////////////////////////////////////////
-  // __iter__ is a special case not handled by the above macros. First
-  // the unspecialized (do-nothing) version
-  //////////////////////////////////////////////////////////////////////////
-
-  template<bool doit>
-  struct maybe_add_iter {
-    template<class PythonClass, class Algorithms, class Policy>
-    static void apply (PythonClass &, Algorithms const &, Policy const &) { }
-  };
-
-  //////////////////////////////////////////////////////////////////////////
-  // Specialization with the real implementation of __iter__
-  //////////////////////////////////////////////////////////////////////////
-
-  template<>
-  struct maybe_add_iter<true> {
-    template<class PythonClass, class Algorithms, class Policy>
-    static void apply(
-        PythonClass &pyClass,
-        Algorithms const &,
-        Policy const &)
-    {
-      // Should maybe separate precall and postcall portions of the
-      // policy (precall when generating the range object, postcall
-      // when returing from range.next())?
-
-      pyClass.def(
-          "__iter__",
-          boost::python::range<Policy>(
-              Algorithms::begin,
-              Algorithms::end));
-    }
-  };
-
-  //////////////////////////////////////////////////////////////////////////
-  // All other optional methods are covered by the two OPTIONAL_*
-  // macros
-  //////////////////////////////////////////////////////////////////////////
-
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_len, "__len__", size);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_getitem, "__getitem__", get);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_setitem, "__setitem__", assign);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_delitem, "__delitem__", erase_one);
-  OPTIONAL_SLICE_SUPPORT (maybe_add_getslice, "__getitem__", make_getitem);
-  OPTIONAL_SLICE_SUPPORT (maybe_add_setslice, "__setitem__", make_setitem);
-  OPTIONAL_SLICE_SUPPORT (maybe_add_delslice, "__delitem__", make_delitem);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_sort, "sort", sort);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_reverse, "reverse", reverse);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_append, "append", push_back);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_insert, "insert", insert);
-  OPTIONAL_SLICE_SUPPORT (maybe_add_extend, "extend", make_extend);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_index, "index", get_index);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_count, "count", count);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_contains, "__contains__", contains);
-  OPTIONAL_ALGO_SUPPORT  (maybe_add_has_key, "has_key", contains);
-
-  //////////////////////////////////////////////////////////////////////////
-  // Do-all visitor
-  //////////////////////////////////////////////////////////////////////////
-
-  template<class Algorithms, class Policy, method_set_type MethodMask>
-  class visitor
-    : public def_visitor< visitor< Algorithms, Policy, MethodMask > >
-  {
-    Policy m_policy;
-
-    BOOST_STATIC_CONSTANT (
-        method_set_type,
-        enabled_methods = Algorithms::supported_methods & MethodMask);
-
-  public:
-    typedef Algorithms algorithms_type;
-
-    explicit visitor (Policy const &policy = Policy()) : m_policy (policy) { }
-
-  public:
-    template <class PythonClass>
-    void visit (PythonClass &pyClass) const
-    {
-      detail::precall_only<Policy> precallPolicy (m_policy);
-
-      maybe_add_len<detail::is_member<enabled_methods, method_len>::value>
-        ::apply(pyClass, algorithms_type(), precallPolicy);
-
-      maybe_add_getitem<
-        detail::is_member<enabled_methods, method_getitem>::value
-      >::apply(pyClass, algorithms_type(), m_policy);
-
-      maybe_add_getslice<
-          detail::is_member<enabled_methods, method_getitem_slice>::value
-      >::apply(pyClass, algorithms_type(), m_policy);
-
-      maybe_add_setitem<
-        detail::is_member<enabled_methods, method_setitem>::value
-      >::apply(pyClass, algorithms_type(), m_policy);
-
-      maybe_add_setslice<
-          detail::is_member<enabled_methods, method_setitem_slice>::value
-      >::apply(pyClass, algorithms_type(), m_policy);
-
-      maybe_add_delitem<
-        detail::is_member<enabled_methods, method_delitem>::value
-      >::apply(pyClass, algorithms_type(), m_policy);
-
-      maybe_add_delslice<
-          detail::is_member<enabled_methods, method_delitem_slice>::value
-      >::apply(pyClass, algorithms_type(), m_policy);
-
-      maybe_add_iter<
-        detail::is_member<enabled_methods, method_iter>::value
-      >::apply (pyClass, algorithms_type(), m_policy);
-
-      maybe_add_sort<
-        detail::is_member<enabled_methods, method_sort>::value
-      >::apply (pyClass, algorithms_type(), precallPolicy);
-
-      maybe_add_reverse<
-        detail::is_member<enabled_methods, method_reverse>::value
-      >::apply (pyClass, algorithms_type(), precallPolicy);
-
-      maybe_add_append<
-        detail::is_member<enabled_methods, method_append>::value
-      >::apply (pyClass, algorithms_type(), precallPolicy);
-
-      maybe_add_insert<
-        detail::is_member<enabled_methods, method_insert>::value
-      >::apply (pyClass, algorithms_type(), precallPolicy);
-
-      maybe_add_extend<
-        detail::is_member<enabled_methods, method_extend>::value
-      >::apply (pyClass, algorithms_type(), precallPolicy);
-
-      maybe_add_index<
-        detail::is_member<enabled_methods, method_index>::value
-      >::apply (pyClass, algorithms_type(), precallPolicy);
-
-      maybe_add_count<
-        detail::is_member<enabled_methods, method_count>::value
-      >::apply (pyClass, algorithms_type(), precallPolicy);
-
-      maybe_add_contains<
-        detail::is_member<enabled_methods, method_contains>::value
-      >::apply (pyClass, algorithms_type(), precallPolicy);
-
-      maybe_add_has_key<
-        detail::is_member<enabled_methods, method_has_key>::value
-      >::apply (pyClass, algorithms_type(), precallPolicy);
-
-      Algorithms::visit_container_class (pyClass, m_policy);
-    }
-  };
-} } }
-
-#undef OPTIONAL_SLICE_SUPPORT
-#undef OPTIONAL_ALGO_SUPPORT
-
-#endif // BOOST_PYTHON_INDEXING_VISITOR_HPP

=== removed file 'py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/workaround.hpp'
--- py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/workaround.hpp	2009-08-23 15:50:47 +0000
+++ py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/workaround.hpp	1970-01-01 00:00:00 +0000
@@ -1,47 +0,0 @@
-// Header file workaround.hpp
-//
-// Indexing-specific workarounds for compiler problems.
-//
-// Copyright (c) 2003 Raoul M. Gough
-//
-// Use, modification and distribution is subject to the Boost Software
-// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy
-// at http://www.boost.org/LICENSE_1_0.txt)
-//
-// History
-// =======
-// 2003/10/21   rmg     File creation
-// 2008/12/08   Roman   Change indexing suite layout
-//
-// $Id: workaround.hpp,v 1.1.2.3 2003/11/17 19:27:13 raoulgough Exp $
-//
-
-#ifndef BOOST_PYTHON_INDEXING_WORKAROUND_HPP
-#define BOOST_PYTHON_INDEXING_WORKAROUND_HPP
-
-#include <boost/config.hpp>
-#include <boost/detail/workaround.hpp>
-
-# if (BOOST_WORKAROUND (__GNUC__, < 3))
-#   // gcc versions before 3 (like 2.95.3) don't have the "at" member
-#   // function in std::vector or std::deque
-#   define BOOST_PYTHON_INDEXING_AT operator[]
-# else
-#   define BOOST_PYTHON_INDEXING_AT at
-# endif
-
-# if BOOST_WORKAROUND (BOOST_MSVC, <= 1300)
-// Workaround the lack of a reset member function in std::auto_ptr
-namespace boost { namespace python { namespace indexing {
-template<typename T> void reset_auto_ptr (T &aptr, T::element_type *pptr) {
- aptr = T (pptr);
-}
-} } }
-#   define BOOST_PYTHON_INDEXING_RESET_AUTO_PTR \
-        ::boost::python::indexing::reset_auto_ptr
-# else
-#   define BOOST_PYTHON_INDEXING_RESET_AUTO_PTR( aptr, pptr ) \
-        (aptr).reset(pptr)
-# endif
-
-#endif // BOOST_PYTHON_INDEXING_WORKAROUND_HPP

=== modified file 'py/CMakeLists.txt'
--- py/CMakeLists.txt	2012-06-06 20:04:55 +0000
+++ py/CMakeLists.txt	2013-03-18 18:47:34 +0000
@@ -1,4 +1,31 @@
+#==================pygts=========================================
+IF(ENABLE_GTS)
+  find_python_module(gts)
+  IF (PY_gts)
+    MESSAGE(STATUS "Use system gts version")
+  ELSE (PY_gts)
+    MESSAGE(STATUS "Use embedded version of gts. Please, consider installing the corresponding package")
+    FILE(GLOB SRC_PYGTS "${CMAKE_CURRENT_SOURCE_DIR}/3rd-party/pygts-0.3.1/*.c")
+    ADD_LIBRARY(_gts SHARED ${SRC_PYGTS})
+    SET_TARGET_PROPERTIES(_gts PROPERTIES PREFIX "")
+    TARGET_LINK_LIBRARIES(_gts gts)
+    INSTALL(FILES 3rd-party/pygts-0.3.1/__init__.py DESTINATION ${YADE_LIB_PATH}/py/gts)
+    INSTALL(FILES 3rd-party/pygts-0.3.1/pygts.py DESTINATION ${YADE_LIB_PATH}/py/gts)
+    INSTALL(TARGETS _gts DESTINATION ${YADE_LIB_PATH}/py/gts)
+  ENDIF (PY_gts)
+ENDIF(ENABLE_GTS)
+#==================pygts=========================================
+
 #==================pyModules=========================================
+
+FILE(GLOB filesPY "${CMAKE_CURRENT_SOURCE_DIR}/*.py")
+SET(filesPY "${filesPY};${CMAKE_CURRENT_SOURCE_DIR}/pack/pack.py")
+INSTALL(FILES ${filesPY} DESTINATION ${YADE_PY_PATH}/yade)
+INSTALL(FILES 3rd-party/mtTkinter-0.3/mtTkinter.py DESTINATION ${YADE_LIB_PATH}/py)
+FILE(GLOB filesPYTests "${CMAKE_CURRENT_SOURCE_DIR}/tests/*.py")
+INSTALL(FILES ${filesPYTests} DESTINATION ${YADE_PY_PATH}/yade/tests)
+FILE(GLOB filesPYPerf "${CMAKE_CURRENT_SOURCE_DIR}/../examples/test/performance/*")
+INSTALL(FILES ${filesPYPerf} DESTINATION ${YADE_PY_PATH}/yade/tests/checks/performance)
 ADD_LIBRARY(WeightedAverage2d SHARED "${CMAKE_CURRENT_SOURCE_DIR}/WeightedAverage2d.cpp")
 SET_TARGET_PROPERTIES(WeightedAverage2d PROPERTIES PREFIX "")
 INSTALL(TARGETS WeightedAverage2d DESTINATION "${YADE_PY_PATH}/yade/")
@@ -17,9 +44,9 @@
 ADD_LIBRARY(_packPredicates SHARED "${CMAKE_CURRENT_SOURCE_DIR}/pack/_packPredicates.cpp")
 SET_TARGET_PROPERTIES(_packPredicates PROPERTIES PREFIX "")
 TARGET_LINK_LIBRARIES(_packPredicates plugins support core)
-IF(ENABLE_GTS)
+IF(ENABLE_GTS AND NOT(PY_gts))
   TARGET_LINK_LIBRARIES(_packPredicates _gts)
-ENDIF(ENABLE_GTS)
+ENDIF(ENABLE_GTS AND NOT(PY_gts))
 
 
 INSTALL(TARGETS _packPredicates DESTINATION "${YADE_PY_PATH}/yade/")
@@ -43,29 +70,6 @@
 TARGET_LINK_LIBRARIES(_customConverters plugins support)
 INSTALL(TARGETS _customConverters DESTINATION "${YADE_PY_PATH}/yade/")
 
-#==================pyModules=========================================
-
-#==================pygts=========================================
-IF(ENABLE_GTS)
-  FILE(GLOB SRC_PYGTS "${CMAKE_CURRENT_SOURCE_DIR}/3rd-party/pygts-0.3.1/*.c")
-  ADD_LIBRARY(_gts SHARED ${SRC_PYGTS})
-  SET_TARGET_PROPERTIES(_gts PROPERTIES PREFIX "")
-  TARGET_LINK_LIBRARIES(_gts gts)
-  INSTALL(FILES 3rd-party/pygts-0.3.1/__init__.py DESTINATION ${YADE_LIB_PATH}/py/gts)
-  INSTALL(FILES 3rd-party/pygts-0.3.1/pygts.py DESTINATION ${YADE_LIB_PATH}/py/gts)
-  INSTALL(TARGETS _gts DESTINATION ${YADE_LIB_PATH}/py/gts)
-ENDIF(ENABLE_GTS)
-#==================pygts=========================================
-
-FILE(GLOB filesPY "${CMAKE_CURRENT_SOURCE_DIR}/*.py")
-SET(filesPY "${filesPY};${CMAKE_CURRENT_SOURCE_DIR}/pack/pack.py")
-INSTALL(FILES ${filesPY} DESTINATION ${YADE_PY_PATH}/yade)
-INSTALL(FILES 3rd-party/mtTkinter-0.3/mtTkinter.py DESTINATION ${YADE_LIB_PATH}/py)
-FILE(GLOB filesPYTests "${CMAKE_CURRENT_SOURCE_DIR}/tests/*.py")
-INSTALL(FILES ${filesPYTests} DESTINATION ${YADE_PY_PATH}/yade/tests)
-FILE(GLOB filesPYPerf "${CMAKE_CURRENT_SOURCE_DIR}/../examples/test/performance/*")
-INSTALL(FILES ${filesPYPerf} DESTINATION ${YADE_PY_PATH}/yade/tests/checks/performance)
-
 
 
 

=== modified file 'py/__init__.py.in'
--- py/__init__.py.in	2012-06-06 20:04:55 +0000
+++ py/__init__.py.in	2013-03-09 06:50:17 +0000
@@ -72,18 +72,46 @@
 globals().update(deprecatedTypes)
 # declare what should be imported for "from yade import *"
 __all__=deprecatedTypes.keys()+['O']
-# fake miniWm3 and wrapper being in yade itself
-from miniEigen import *
+
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
+
 from wrapper import *
 # import to separate namespace to be able to call dir(miniEigen) and dir(wrapper) below
-import miniEigen,wrapper 
+import wrapper 
+
+try:
+	import minieigen
+except ImportError:
+	import miniEigen
+
 # out-of-class docstrings for some classes
 import _extraDocs
 # import a few "important" modules along with *
 import utils # some others?
-__all__+=['utils',]+dir(miniEigen)+dir(wrapper)
+__all__+=['utils',]+dir(wrapper)
+
+try:
+	__all__+=dir(miniEigen)
+except NameError:
+	pass
+
 # make O and wrapper.Omega part of __builtin__ (equvialent to global)
 import __builtin__
 __builtin__.__dict__['O'] = O
 __builtin__.__dict__['Omega'] = wrapper.Omega
+# define a default list of engine
+O.engines=[
+		ForceResetter(),
+		InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb(),Bo1_Box_Aabb()]),
+		InteractionLoop(
+			[Ig2_Sphere_Sphere_ScGeom(),Ig2_Facet_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom()],
+			[Ip2_FrictMat_FrictMat_FrictPhys()],	#for linear model only
+			[Law2_ScGeom_FrictPhys_CundallStrack()],	#for linear model only
+		),
+		GlobalStiffnessTimeStepper(timeStepUpdateInterval=10),
+		NewtonIntegrator()
+	]
 

=== modified file 'py/_eudoxos.cpp'
--- py/_eudoxos.cpp	2012-06-05 18:39:33 +0000
+++ py/_eudoxos.cpp	2013-03-07 18:28:01 +0000
@@ -4,7 +4,8 @@
 
 #include<yade/pkg/dem/ConcretePM.hpp>
 #include<boost/python.hpp>
-#include<yade/extra/boost_python_len.hpp>
+#include<boost/python/object.hpp>
+#include<boost/version.hpp>
 #include<yade/pkg/dem/Shop.hpp>
 #include<yade/pkg/dem/DemXDofGeom.hpp>
 
@@ -156,7 +157,7 @@
 			boost::tie(r,h,theta)=Shop::spiralProject(ge->contactPoint,dH_dTheta,axis,periodStart,theta0);
 			if(!isnan(thetaMin) && theta<thetaMin) continue;
 			if(!isnan(thetaMax) && theta>thetaMax) continue;
-			lo=lo.cwise().min(Vector2r(r,h)); hi=hi.cwise().max(Vector2r(r,h));
+			lo=lo.cwiseMin(Vector2r(r,h)); hi=hi.cwiseMax(Vector2r(r,h));
 			minD0=min(minD0,ge->refLength); maxD0=max(maxD0,ge->refLength);
 			minTheta=min(minTheta,theta); maxTheta=max(maxTheta,theta);
 			intrs.push_back(FlatInteraction(r,h,theta,i));

=== modified file 'py/_utils.cpp'
--- py/_utils.cpp	2012-11-13 14:32:37 +0000
+++ py/_utils.cpp	2013-04-02 13:57:36 +0000
@@ -1,6 +1,7 @@
 #include<yade/pkg/dem/Shop.hpp>
 #include<boost/python.hpp>
-#include<yade/extra/boost_python_len.hpp>
+#include<boost/python/object.hpp>
+#include<boost/version.hpp>
 #include<yade/core/Scene.hpp>
 #include<yade/core/Omega.hpp>
 #include<yade/pkg/dem/ScGeom.hpp>
@@ -28,8 +29,8 @@
 	FOREACH(const shared_ptr<Body>& b, *Omega::instance().getScene()->bodies){
 		shared_ptr<Sphere> s=dynamic_pointer_cast<Sphere>(b->shape); if(!s) continue;
 		Vector3r rrr(s->radius,s->radius,s->radius);
-		minimum=minimum.cwise().min(b->state->pos-(centers?Vector3r::Zero():rrr));
-		maximum=maximum.cwise().max(b->state->pos+(centers?Vector3r::Zero():rrr));
+		minimum=minimum.cwiseMin(b->state->pos-(centers?Vector3r::Zero():rrr));
+		maximum=maximum.cwiseMax(b->state->pos+(centers?Vector3r::Zero():rrr));
 	}
 	Vector3r dim=maximum-minimum;
 	return py::make_tuple(Vector3r(minimum+.5*cutoff*dim),Vector3r(maximum-.5*cutoff*dim));
@@ -145,16 +146,27 @@
 	FOREACH(const shared_ptr<Interaction>& i, *rb->interactions){
 		if(!i->isReal()) continue;
 		const Body::id_t id1=i->getId1(), id2=i->getId2(); const shared_ptr<Body>& b1=Body::byId(id1,rb), b2=Body::byId(id2,rb);
-		if((useBB && isInBB(b1->state->pos,bbMin,bbMax)) || !useBB) bodyNumIntr[id1]+=1;
-		if((useBB && isInBB(b2->state->pos,bbMin,bbMax)) || !useBB) bodyNumIntr[id2]+=1;
+		if((useBB && isInBB(b1->state->pos,bbMin,bbMax)) || !useBB) {
+			if (b1->isClumpMember()) bodyNumIntr[b1->clumpId]+=1; //count bodyNumIntr for the clump, not for the member 
+			else bodyNumIntr[id1]+=1;
+		}
+		if((useBB && isInBB(b2->state->pos,bbMin,bbMax)) || !useBB) {
+			if (b2->isClumpMember()) bodyNumIntr[b2->clumpId]+=1; //count bodyNumIntr for the clump, not for the member 
+			else bodyNumIntr[id2]+=1;
+		}
 		maxIntr=max(max(maxIntr,bodyNumIntr[b1->getId()]),bodyNumIntr[b2->getId()]);
+		if (b1->isClumpMember()) maxIntr=max(maxIntr,bodyNumIntr[b1->clumpId]);
+		if (b2->isClumpMember()) maxIntr=max(maxIntr,bodyNumIntr[b2->clumpId]);
 	}
 	vector<int> bins; bins.resize(maxIntr+1,0);
 	for(size_t id=0; id<bodyNumIntr.size(); id++){
-		if(bodyNumIntr[id]>0) bins[bodyNumIntr[id]]+=1;
-		// 0 is handled specially: add body to the 0 bin only if it is inside the bb requested (if applicable)
-		// otherwise don't do anything, since it is outside the volume of interest
-		else if((useBB && isInBB(Body::byId(id,rb)->state->pos,bbMin,bbMax)) || !useBB) bins[0]+=1;
+		const shared_ptr<Body>& b=Body::byId(id,rb);
+		if (b) {
+			if(bodyNumIntr[id]>0) bins[bodyNumIntr[id]]+=1;
+			// 0 is handled specially: add body to the 0 bin only if it is inside the bb requested (if applicable)
+			// otherwise don't do anything, since it is outside the volume of interest
+			else if(((useBB && isInBB(b->state->pos,bbMin,bbMax)) || !useBB) && !(b->isClumpMember())) bins[0]+=1;
+		}
 	}
 	py::list count,num;
 	for(size_t n=0; n<bins.size(); n++){
@@ -303,24 +315,6 @@
 	return inside;
 }
 
-#if 0
-/* Compute convex hull of given points, given as python list of Vector2 */
-py::list convexHull2d(const py::list& pts){
-	size_t l=py::len(pts);
-	py::list ret;
-	std::list<Vector2r> pts2;
-	for(size_t i=0; i<l; i++){
-		pts2.push_back(py::extract<Vector2r>(pts[i]));
-		cerr<<*pts2.rbegin()<<endl;
-	}
-	ConvexHull2d ch2d(pts2);
-	vector<Vector2r> hull=ch2d();
-	FOREACH(const Vector2r& v, hull) ret.append(v);
-	cout<<pts2.size()<<" "<<hull.size()<<"@@@"<<endl;
-	return ret;
-}
-#endif 
-
 /* Compute area of convex hull when when taking (swept) spheres crossing the plane at coord, perpendicular to axis.
 
 	All spheres that touch the plane are projected as hexagons on their circumference to the plane.
@@ -457,6 +451,42 @@
 	b->state->pos = center;
 }
 
+py::list intrsOfEachBody() {
+	py::list ret, temp;
+	shared_ptr<Scene> rb=Omega::instance().getScene();
+	size_t n = rb->bodies->size();
+	// create list of size len(O.bodies) full of zeros
+	for (size_t i=0; i<n; i++) {
+		ret.append(py::list());
+	}
+	// loop over all interactions and fill the list ret
+	FOREACH(const shared_ptr<Interaction>& i, *rb->interactions) {
+		if (!i->isReal()) { continue; }
+		temp = py::extract<py::list>(ret[i->getId1()]);
+		temp.append( i );
+		temp = py::extract<py::list>(ret[i->getId2()]);
+		temp.append( i );
+	}
+	return ret;
+}
+
+py::list numIntrsOfEachBody() {
+	py::list ret;
+	shared_ptr<Scene> rb=Omega::instance().getScene();
+	size_t n = rb->bodies->size();
+	// create list of size len(O.bodies) full of zeros
+	for (size_t i=0; i<n; i++) {
+		ret.append(0);
+	}
+	// loop over all interactions and fill the list ret
+	FOREACH(const shared_ptr<Interaction>& i, *rb->interactions) {
+		if (!i->isReal()) continue;
+		ret[i->getId1()] += 1;
+		ret[i->getId2()] += 1;
+	}
+	return ret;
+}
+
 BOOST_PYTHON_MODULE(_utils){
 	// http://numpy.scipy.org/numpydoc/numpy-13.html mentions this must be done in module init, otherwise we will crash
 	import_array();
@@ -473,9 +503,6 @@
 	py::def("ptInAABB",isInBB,"Return True/False whether the point p is within box given by its min and max corners");
 	py::def("negPosExtremeIds",negPosExtremeIds,negPosExtremeIds_overloads(py::args("axis","distFactor"),"Return list of ids for spheres (only) that are on extremal ends of the specimen along given axis; distFactor multiplies their radius so that sphere that do not touch the boundary coordinate can also be returned."));
 	py::def("approxSectionArea",approxSectionArea,"Compute area of convex hull when when taking (swept) spheres crossing the plane at coord, perpendicular to axis.");
-	#if 0
-		py::def("convexHull2d",convexHull2d,"Return 2d convex hull of list of 2d points, as list of polygon vertices.");
-	#endif
 	py::def("coordsAndDisplacements",coordsAndDisplacements,(python::arg("axis"),python::arg("Aabb")=python::tuple()),"Return tuple of 2 same-length lists for coordinates and displacements (coordinate minus reference coordinate) along given axis (1st arg); if the Aabb=((x_min,y_min,z_min),(x_max,y_max,z_max)) box is given, only bodies within this box will be considered.");
 	py::def("setRefSe3",setRefSe3,"Set reference :yref:`positions<State::refPos>` and :yref:`orientations<State::refOri>` of all :yref:`bodies<Body>` equal to their current :yref:`positions<State::pos>` and :yref:`orientations<State::ori>`.");
 	py::def("interactionAnglesHistogram",interactionAnglesHistogram,interactionAnglesHistogram_overloads(py::args("axis","mask","bins","aabb")));
@@ -504,8 +531,8 @@
 	//py::def("stressTensorOfPeriodicCell",Shop__stressTensorOfPeriodicCell,(py::args("smallStrains")=false),"Compute overall (macroscopic) stress of periodic cell using equation published in [Kuhl2001]_:\n\n.. math:: \\vec{\\sigma}=\\frac{1}{V}\\sum_cl^c[\\vec{N}^cf_N^c+\\vec{T}^{cT}\\cdot\\vec{f}^c_T],\n\nwhere $V$ is volume of the cell, $l^c$ length of interaction $c$, $f^c_N$ normal force and $\\vec{f}^c_T$ shear force. Sumed are values over all interactions $c$. $\\vec{N}^c$ and $\\vec{T}^{cT}$ are projection tensors (see the original publication for more details):\n\n.. math:: \\vec{N}=\\vec{n}\\otimes\\vec{n}\\rightarrow N_{ij}=n_in_j\n\n.. math:: \\vec{T}^T=\\vec{I}_{sym}\\cdot\\vec{n}-\\vec{n}\\otimes\\vec{n}\\otimes\\vec{n}\\rightarrow T^T_{ijk}=\\frac{1}{2}(\\delta_{ik}\\delta_{jl}+\\delta_{il}\\delta_{jk})n_l-n_in_jn_k\n\n.. math:: \\vec{T}^T\\cdot\\vec{f}_T\\equiv T^T_{ijk}f_k=(\\delta_{ik}n_j/2+\\delta_{jk}n_i/2-n_in_jn_k)f_k=n_jf_i/2+n_if_j/2-n_in_jn_kf_k,\n\nwhere $n$ is unit vector oriented along the interaction (:yref:`normal<GenericSpheresContact::normal>`) and $\\delta$ is Kronecker's delta. As $\\vec{n}$ and $\\vec{f}_T$ are perpendicular (therfore $n_if_i=0$) we can write\n\n.. math:: \\sigma_{ij}=\\frac{1}{V}\\sum l[n_in_jf_N+n_jf^T_i/2+n_if^T_j/2]\n\n:param bool smallStrains: if false (large strains), real values of volume and interaction lengths are computed. If true, only :yref:`refLength<Dem3DofGeom::refLength>` of interactions and initial volume are computed (can save some time).\n\n:return: macroscopic stress tensor as Matrix3");
 	py::def("normalShearStressTensors",Shop__normalShearStressTensors,(py::args("compressionPositive")=false,py::args("splitNormalTensor")=false,py::args("thresholdForce")=NaN),"Compute overall stress tensor of the periodic cell decomposed in 2 parts, one contributed by normal forces, the other by shear forces. The formulation can be found in [Thornton2000]_, eq. (3):\n\n.. math:: \\tens{\\sigma}_{ij}=\\frac{2}{V}\\sum R N \\vec{n}_i \\vec{n}_j+\\frac{2}{V}\\sum R T \\vec{n}_i\\vec{t}_j\n\nwhere $V$ is the cell volume, $R$ is \"contact radius\" (in our implementation, current distance between particle centroids), $\\vec{n}$ is the normal vector, $\\vec{t}$ is a vector perpendicular to $\\vec{n}$, $N$ and $T$ are norms of normal and shear forces.\n\n:param bool splitNormalTensor: if true the function returns normal stress tensor split into two parts according to the two subnetworks of strong an weak forces.\n\n:param Real thresholdForce: threshold value according to which the normal stress tensor can be split (e.g. a zero value would make distinction between tensile and compressive forces).");
 	py::def("fabricTensor",Shop__fabricTensor,(py::args("splitTensor")=false,py::args("revertSign")=false,py::args("thresholdForce")=NaN),"Compute the fabric tensor of the periodic cell. The original paper can be found in [Satake1982]_.\n\n:param bool splitTensor: split the fabric tensor into two parts related to the strong and weak contact forces respectively.\n\n:param bool revertSign: it must be set to true if the contact law's convention takes compressive forces as positive.\n\n:param Real thresholdForce: if the fabric tensor is split into two parts, a threshold value can be specified otherwise the mean contact force is considered by default. It is worth to note that this value has a sign and the user needs to set it according to the convention adopted for the contact law. To note that this value could be set to zero if one wanted to make distinction between compressive and tensile forces.");
-	py::def("bodyStressTensors",Shop__getStressLWForEachBody,"Compute and return a table with per-particle stress tensors. Each tensor represents the average stress in one particle, obtained from the contour integral of applied load as detailed below. This definition is considering each sphere as a continuum. It can be considered exact in the context of spheres at static equilibrium, interacting at contact points with negligible volume changes of the solid phase (this last assumption is not restricting possible deformations and volume changes at the packing scale).\n\nProof:\n\nFirst, we remark the identity:  $\\sigma_{ij}=\\delta_{ij}\\sigma_{ij}=x_{i,j}\\sigma_{ij}=(x_{i}\\sigma_{ij})_{,j}-x_{i}\\sigma_{ij,j}$.\n\nAt equilibrium, the divergence of stress is null: $\\sigma_{ij,j}=\\vec{0}$. Consequently, after divergence theorem: $\\frac{1}{V}\\int_V \\sigma_{ij}dV = \\frac{1}{V}\\int_V (x_{i}\\sigma_{ij})_{,j}dV = \\frac{1}{V}\\int_{\\partial V}x_i.\\sigma_{ij}.\\vec{n_j}.dS = \\frac{1}{V}\\sum_kx_i^k.f_j^k$.\n\nThe last equality is implicitely based on the representation of external loads as Dirac distributions whose zeros are the so-called *contact points*: 0-sized surfaces on which the *contact forces* are applied, located at $x_i$ in the deformed configuration.\n\nA weighted average of per-body stresses will give the average stress inside the solid phase. There is a simple relation between the stress inside the solid phase and the stress in an equivalent continuum in the absence of fluid pressure. For porosity $n$, the relation reads: $\\sigma_{ij}^{equ.}=(1-n)\\sigma_{ij}^{solid}$.");
-	py::def("getStress",Shop::getStress,(py::args("volume")=0),"Compute and return Love-Weber stress tensor:\n\n $\\sigma_{ij}=\\frac{1}{V}\\sum l_i f_j^k$, where the sum is over all interactions, with $l$ the branch vector (joining centers of the bodies) and $f$ is the contact force. $V$ can be passed to the function. If it is not, it will be equal to one in non-periodic cases, or equal to the volume of the cell in periodic cases.");
+	py::def("bodyStressTensors",Shop__getStressLWForEachBody,"Compute and return a table with per-particle stress tensors. Each tensor represents the average stress in one particle, obtained from the contour integral of applied load as detailed below. This definition is considering each sphere as a continuum. It can be considered exact in the context of spheres at static equilibrium, interacting at contact points with negligible volume changes of the solid phase (this last assumption is not restricting possible deformations and volume changes at the packing scale).\n\nProof:\n\nFirst, we remark the identity:  $\\sigma_{ij}=\\delta_{ik}\\sigma_{kj}=x_{i,k}\\sigma_{kj}=(x_{i}\\sigma_{kj})_{,k}-x_{i}\\sigma_{kj,k}$.\n\nAt equilibrium, the divergence of stress is null: $\\sigma_{kj,k}=\\vec{0}$. Consequently, after divergence theorem: $\\frac{1}{V}\\int_V \\sigma_{ij}dV = \\frac{1}{V}\\int_V (x_{i}\\sigma_{kj})_{,k}dV = \\frac{1}{V}\\int_{\\partial V}x_i\\sigma_{kj}n_kdS = \\frac{1}{V}\\sum_bx_i^bf_j^b$.\n\nThe last equality is implicitely based on the representation of external loads as Dirac distributions whose zeros are the so-called *contact points*: 0-sized surfaces on which the *contact forces* are applied, located at $x_i$ in the deformed configuration.\n\nA weighted average of per-body stresses will give the average stress inside the solid phase. There is a simple relation between the stress inside the solid phase and the stress in an equivalent continuum in the absence of fluid pressure. For porosity $n$, the relation reads: $\\sigma_{ij}^{equ.}=(1-n)\\sigma_{ij}^{solid}$.");
+	py::def("getStress",Shop::getStress,(py::args("volume")=0),"Compute and return Love-Weber stress tensor:\n\n $\\sigma_{ij}=\\frac{1}{V}\\sum_b l_i^b f_j^b$, where the sum is over all interactions, with $l$ the branch vector (joining centers of the bodies) and $f$ is the contact force. $V$ can be passed to the function. If it is not, it will be equal to one in non-periodic cases, or equal to the volume of the cell in periodic cases.");
 	py::def("getBodyIdsContacts",Shop__getBodyIdsContacts,(py::args("bodyID")=0),"Get a list of body-ids, which contacts the given body.");
 	py::def("maxOverlapRatio",maxOverlapRatio,"Return maximum overlap ration in interactions (with :yref:`ScGeom`) of two :yref:`spheres<Sphere>`. The ratio is computed as $\\frac{u_N}{2(r_1 r_2)/r_1+r_2}$, where $u_N$ is the current overlap distance and $r_1$, $r_2$ are radii of the two spheres in contact.");
 	py::def("shiftBodies",shiftBodies,(py::arg("ids"),py::arg("shift")),"Shifts bodies listed in ids without updating their velocities.");
@@ -513,4 +540,6 @@
 	py::def("setNewVerticesOfFacet",setNewVerticesOfFacet,(py::arg("b"),py::arg("v1"),py::arg("v2"),py::arg("v3")),"Sets new vertices (in global coordinates) to given facet.");
 	py::def("setContactFriction",Shop::setContactFriction,py::arg("angleRad"),"Modify the friction angle (in radians) inside the material classes and existing contacts. The friction for non-dynamic bodies is not modified.");
 	py::def("growParticles",Shop::growParticles,(py::args("multiplier"), py::args("updateMass")=true, py::args("dynamicOnly")=true), "Change the size of spheres and sphere clumps by the multiplier. If updateMass=True, then the mass is updated. dynamicOnly=True is mandatory in many cases since in current implementation the function would crash on the non-spherical and non-dynamic bodies (e.g. facets, boxes, etc.)");
+	py::def("intrsOfEachBody",intrsOfEachBody,"returns list of lists of interactions of each body");
+	py::def("numIntrsOfEachBody",numIntrsOfEachBody,"returns list of number of interactions of each body");
 }

=== modified file 'py/bodiesHandling.py'
--- py/bodiesHandling.py	2012-09-08 01:19:45 +0000
+++ py/bodiesHandling.py	2013-03-08 21:26:47 +0000
@@ -4,9 +4,13 @@
 """
 
 from yade.wrapper import *
-from miniEigen import *
 import utils,math,numpy
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
+
 #spheresPackDimensions==================================================
 def spheresPackDimensions(idSpheres=[],mask=-1):
 	"""The function accepts the list of spheres id's or list of bodies and calculates max and min dimensions, geometrical center.

=== modified file 'py/eudoxos.py'
--- py/eudoxos.py	2011-08-29 18:23:23 +0000
+++ py/eudoxos.py	2013-04-24 19:49:00 +0000
@@ -35,7 +35,7 @@
 		>>> from yade import utils
 		>>> O.bodies.append([utils.sphere((0,0,0),1),utils.sphere((0,0,1.9),1)])
 		[0, 1]
-		>>> O.engines=[InteractionLoop([Ig2_Sphere_Sphere_Dem3DofGeom(),],[Ip2_FrictMat_FrictMat_FrictPhys()],[])]
+		>>> O.engines=[InteractionLoop([Ig2_Sphere_Sphere_ScGeom(),],[Ip2_FrictMat_FrictMat_FrictPhys()],[])]
 		>>> utils.createInteraction(0,1) #doctest: +ELLIPSIS
 		<Interaction instance at 0x...>
 
@@ -127,7 +127,7 @@
 	The format is line-oriented as follows::
 
 		E G                                                 # elastic material parameters
-		epsCrackOnset crackOpening xiShear transStrainCoeff # tensile parameters; epsFr=crackOpening/len
+		epsCrackOnset relDuctility xiShear transStrainCoeff # tensile parameters; epsFr=epsCrackOnset*relDuctility
 		cohesionT tanPhi                                    # shear parameters
 		number_of_spheres number_of_links
 		id x y z r boundary                                 # spheres; boundary: -1 negative, 0 none, 1 positive

=== modified file 'py/export.py'
--- py/export.py	2012-10-15 14:05:38 +0000
+++ py/export.py	2013-04-08 15:51:39 +0000
@@ -46,6 +46,7 @@
 	out.close()
 	return count
 
+#VTKWriter===============================================================
 class VTKWriter:
 	"""
 	USAGE:
@@ -174,7 +175,7 @@
 
 
 
-
+#VTKExporter===============================================================
 
 class VTKExporter:
 	"""Class for exporting data to VTK Simple Legacy File (for example if, for some reason, you are not able to use VTKRecorder). Export of spheres and facets is supported.
@@ -376,3 +377,115 @@
 					outFile.write("%g\n"%(eval(command)))
 		outFile.close()
 		self.facetsSnapCount += 1
+
+#gmshGeoExport===============================================================
+def gmshGeo(filename, comment='',mask=-1,accuracy=-1):
+	"""Save spheres in geo-file for the following using in GMSH (http://www.geuz.org/gmsh/doc/texinfo/) program. The spheres can be there meshed.
+
+	:param string filename: the name of the file, where sphere coordinates will be exported.
+	:param int mask: export only spheres with the corresponding mask export only spheres with the corresponding mask
+	:param float accuracy: the accuracy parameter, which will be set for the poinst in geo-file. By default: 1./10. of the minimal sphere diameter.
+	:return: number of spheres which were exported.
+	:rtype: int
+	"""
+	O=Omega()
+	
+	try:
+		out=open(filename,'w')
+	except:
+		raise RuntimeError("Problem to write into the file")
+	
+	count=0
+	#out.write('#format \n')
+	# Find the minimal diameter
+	if (accuracy<0.0):
+		dMin = -1.0
+		for b in O.bodies:
+			try:
+				if (isinstance(b.shape,Sphere) and ((mask<0) or ((mask&b.mask)>0))):
+					if (((dMin>0.0) and (dMin>b.shape.radius*2.0)) or (dMin<0.0)):
+						dMin = b.shape.radius*2.0
+			except AttributeError:
+				pass
+		accuracy = dMin/10.0
+	# Export bodies
+	PTS = 0
+	CRS = 0
+	out.write('Acc = %g;\n'%(accuracy))
+	for b in O.bodies:
+		try:
+			if (isinstance(b.shape,Sphere) and ((mask<0) or ((mask&b.mask)>0))):
+				r = b.shape.radius
+				x = b.state.pos[0]
+				y = b.state.pos[1]
+				z = b.state.pos[2]
+				out.write('Rad = %g;\n'%(r))
+				out.write('Point(%d) = {%g, %g, %g, Acc};\n\
+Point(%d) = {%g, %g, %g, Acc};\n\
+Point(%d) = {%g, %g, %g, Acc};\n\
+Point(%d) = {%g, %g, %g, Acc};\n\
+Point(%d) = {%g, %g, %g, Acc};\n\
+Point(%d) = {%g, %g, %g, Acc};\n\
+Point(%d) = {%g, %g, %g, Acc};\n\n'%(
+				PTS+1, x, y, z, 
+				PTS+2, r+x, y, z, 
+				PTS+3, -r+x, y, z, 
+				PTS+4, x, y, r+z, 
+				PTS+5, x, y, -r+z, 
+				PTS+6, x, r+y, z, 
+				PTS+7, x, -r+y, z
+				))
+				out.write('\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n\
+Circle(%d) = {%d, %d, %d};\n'%(
+				CRS+1, PTS+4, PTS+1, PTS+6,
+				CRS+2, PTS+6, PTS+1, PTS+5,
+				CRS+3, PTS+6, PTS+1, PTS+3,
+				CRS+4, PTS+3, PTS+1, PTS+7,
+				CRS+5, PTS+7, PTS+1, PTS+5,
+				CRS+6, PTS+7, PTS+1, PTS+2,
+				CRS+7, PTS+2, PTS+1, PTS+6,
+				CRS+8, PTS+7, PTS+1, PTS+4,
+				CRS+9, PTS+2, PTS+1, PTS+5,
+				CRS+10, PTS+5, PTS+1, PTS+3,
+				CRS+11, PTS+3, PTS+1, PTS+4,
+				CRS+12, PTS+4, PTS+1, PTS+2,
+				))
+				
+				out.write('\n\
+Line Loop(%d) = {%d, %d, %d}; Ruled Surface(%d) = {%d};\n\
+Line Loop(%d) = {%d, %d, %d}; Ruled Surface(%d) = {%d};\n\
+Line Loop(%d) = {%d, %d, %d}; Ruled Surface(%d) = {%d};\n\
+Line Loop(%d) = {%d, %d, %d}; Ruled Surface(%d) = {%d};\n\
+Line Loop(%d) = {%d, %d, %d}; Ruled Surface(%d) = {%d};\n\
+Line Loop(%d) = {%d, %d, %d}; Ruled Surface(%d) = {%d};\n\
+Line Loop(%d) = {%d, %d, %d}; Ruled Surface(%d) = {%d};\n\
+Line Loop(%d) = {%d, %d, %d}; Ruled Surface(%d) = {%d};\n\n\
+'%(
+				(CRS+13), +(CRS+1), -(CRS+7), -(CRS+12), (CRS+14), (CRS+13),
+				(CRS+15), +(CRS+7), +(CRS+2), -(CRS+9), (CRS+16), (CRS+15),
+				(CRS+17), +(CRS+2), +(CRS+10), -(CRS+3), (CRS+18), (CRS+17),
+				(CRS+19), +(CRS+3), +(CRS+11), +(CRS+1), (CRS+20), (CRS+19),
+				(CRS+21), +(CRS+8), +(CRS+12), -(CRS+6), (CRS+22), (CRS+21),
+				(CRS+23), +(CRS+4), +(CRS+8), -(CRS+11), (CRS+24), (CRS+23),
+				(CRS+25), +(CRS+5), +(CRS+10), (CRS+4), (CRS+26), (CRS+25),
+				(CRS+27), +(CRS+6), +(CRS+9), -(CRS+5), (CRS+28), (CRS+27),
+				))
+				PTS+=7
+				CRS+=28
+				
+				count+=1
+		except AttributeError:
+			pass
+	out.close()
+	return count

=== modified file 'py/geom.py'
--- py/geom.py	2012-09-27 20:07:35 +0000
+++ py/geom.py	2013-03-08 21:26:47 +0000
@@ -4,9 +4,13 @@
 """
 
 from yade.wrapper import *
-from miniEigen import *
 import utils,math,numpy
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
+
 #facetBox===============================================================
 def facetBox(center,extents,orientation=Quaternion.Identity,wallMask=63,**kw):
 	"""

=== removed file 'py/manpage.py'
--- py/manpage.py	2010-06-18 13:02:01 +0000
+++ py/manpage.py	1970-01-01 00:00:00 +0000
@@ -1,88 +0,0 @@
-# coding: utf-8
-#
-# Thanks to logilab for this code.
-#
-# Copied from the logilab.common.optik_ext module (GPL-licensed) and modified for yade.
-#
-
-import optparse,time
-
-class ManHelpFormatter(optparse.HelpFormatter):
-	"""Format help using man pages ROFF format"""
-	def __init__(self,indent_increment=0,max_help_position=24,width=79,short_first=0):
-		optparse.HelpFormatter.__init__(self, indent_increment, max_help_position, width, short_first)
-	def format_heading(self, heading):
-		return '.SH %s\n' % heading.upper()
-	def format_description(self, description):
-		return description
-	def format_option(self, option):
-		try:
-			optstring = option.option_strings
-		except AttributeError:
-			optstring = self.format_option_strings(option)
-		if option.help:
-			help = ' '.join([l.strip() for l in option.help.splitlines()])
-		else:
-			help = ''
-		return '''.IP "%s"
-%s
-''' % (optstring, help)
-	def format_head(self, optparser, metadata, section=1):
-		pgm = optparser.get_prog_name()
-		short_desc = self.format_short_description(pgm, metadata['short_desc'])
-		long_desc = self.format_long_description(pgm, metadata['long_desc'])
-		return '%s\n%s\n%s\n%s' % (self.format_title(pgm, section), short_desc, self.format_synopsis(optparser), long_desc)
-	def format_title(self, pgm, section):
-		date = '-'.join([str(num) for num in time.localtime()[:3]])
-		return '.TH %s %s "%s" %s' % (pgm, section, date, pgm)
-	def format_short_description(self, pgm, short_desc):
-		return '''.SH NAME
-.B %s 
-\- %s
-''' % (pgm, short_desc.strip())
-	def _markup(self, txt):
-		"""Prepares txt to be used in man pages."""
-		return txt.replace('-', '\\-')
-	def format_synopsis(self, optparser):
-		synopsis = optparser.get_usage()
-		pgm=optparser.get_prog_name()                                    
-		if synopsis:                                                           
-			synopsis = synopsis.replace('Usage: %s '%pgm, '')                   
-			return '.SH SYNOPSIS\n.B %s\n%s\n' % (self._markup(pgm),synopsis)
-	def format_long_description(self, pgm, long_desc):
-		long_desc = '\n'.join([line.lstrip()
-								for line in long_desc.splitlines()])
-		long_desc = long_desc.replace('\n.\n', '\n\n')
-		if long_desc.lower().startswith(pgm):
-			long_desc = long_desc[len(pgm):]
-		return '''.SH DESCRIPTION
-.B %s 
-%s
-''' % (pgm, long_desc.strip())
-		 
-	def format_tail(self, metadata, seealso=None):
-		
-		return ('.SH SEE ALSO\n%s\n'%seealso if seealso else '')+'''.SH COPYRIGHT 
-%s %s
-
-%s
-
-.SH BUGS 
-Please report bugs to the project\'s bug tracker at
-.br
-%s
-
-.SH AUTHOR
-%s (%s)
-''' % (metadata['copyright'],metadata['author'],metadata['license'],metadata['bugtracker'],metadata['author'],metadata['author_contact'])
-
-
-def generate_manpage(optparser,metadata,fileOut,seealso=None,section=1):
-	"""generate a man page from an optparse parser"""
-	out=open(fileOut,'w')
-	formatter=ManHelpFormatter()
-	formatter.parser=optparser
-	out.write(formatter.format_head(optparser,metadata,section))
-	out.write(optparser.format_option_help(formatter))
-	out.write(formatter.format_tail(metadata,seealso))
-

=== modified file 'py/mathWrap/miniEigen.cpp'
--- py/mathWrap/miniEigen.cpp	2012-01-31 18:21:29 +0000
+++ py/mathWrap/miniEigen.cpp	2013-03-07 18:28:01 +0000
@@ -116,10 +116,10 @@
 static Real Vector2i_dot(const Vector2i& self, const Vector2i& v){ return self.dot(v); }
 static Vector3r Vector3r_cross(const Vector3r& self, const Vector3r& v){ return self.cross(v); }
 static Vector3i Vector3i_cross(const Vector3i& self, const Vector3i& v){ return self.cross(v); }
-static Vector3r Vector6r_head(const Vector6r& self){ return self.start<3>(); }
-static Vector3r Vector6r_tail(const Vector6r& self){ return self.end<3>(); }
-static Vector3i Vector6i_head(const Vector6i& self){ return self.start<3>(); }
-static Vector3i Vector6i_tail(const Vector6i& self){ return self.end<3>(); }
+static Vector3r Vector6r_head(const Vector6r& self){ return self.head<3>(); }
+static Vector3r Vector6r_tail(const Vector6r& self){ return self.tail<3>(); }
+static Vector3i Vector6i_head(const Vector6i& self){ return self.head<3>(); }
+static Vector3i Vector6i_tail(const Vector6i& self){ return self.tail<3>(); }
 static bool Quaternionr__eq__(const Quaternionr& q1, const Quaternionr& q2){ return q1==q2; }
 static bool Quaternionr__neq__(const Quaternionr& q1, const Quaternionr& q2){ return q1!=q2; }
 #include<Eigen/SVD>
@@ -361,7 +361,6 @@
 		//.add_static_property("UnitX",&Vector6i_UnitX).add_static_property("UnitY",&Vector6i_UnitY).add_static_property("UnitZ",&Vector6i_UnitZ)
 		// methods
 		//.def("dot",&Vector6i_dot).def("cross",&Vector6i_cross)
-		.def("norm",&Vector6i::norm).def("squaredNorm",&Vector6i::squaredNorm).def("normalize",&Vector6i::normalize).def("normalized",&Vector6i::normalized)
 		.def("head",&Vector6i_head).def("tail",&Vector6i_tail)
 		// operators
 		.def("__neg__",&Vector6i__neg__) // -v
@@ -410,7 +409,6 @@
 		.add_static_property("UnitX",&Vector3i_UnitX).add_static_property("UnitY",&Vector3i_UnitY).add_static_property("UnitZ",&Vector3i_UnitZ)
 		// methods
 		.def("dot",&Vector3i_dot).def("cross",&Vector3i_cross)
-		.def("norm",&Vector3i::norm).def("squaredNorm",&Vector3i::squaredNorm)
 		// operators
 		.def("__neg__",&Vector3i__neg__) // -v
 		.def("__add__",&Vector3i__add__Vector3i).def("__iadd__",&Vector3i__iadd__Vector3i) // +, +=
@@ -455,7 +453,6 @@
 		.add_static_property("UnitX",&Vector2i_UnitX).add_static_property("UnitY",&Vector2i_UnitY)
 		// methods
 		.def("dot",&Vector2i_dot)
-		.def("norm",&Vector2i::norm).def("squaredNorm",&Vector2i::squaredNorm).def("normalize",&Vector2i::normalize)
 		// operators
 		.def("__neg__",&Vector2i__neg__) // -v
 		.def("__add__",&Vector2i__add__Vector2i).def("__iadd__",&Vector2i__iadd__Vector2i) // +, +=

=== modified file 'py/pack/_packObb.cpp'
--- py/pack/_packObb.cpp	2010-11-07 11:46:20 +0000
+++ py/pack/_packObb.cpp	2013-03-07 18:28:01 +0000
@@ -4,7 +4,8 @@
 
 #include<boost/python.hpp>
 #include<boost/foreach.hpp>
-#include<yade/extra/boost_python_len.hpp>
+#include<boost/python/object.hpp>
+#include<boost/version.hpp>
 #include<yade/lib/base/Logging.hpp>
 #include<yade/lib/base/Math.hpp>
 #include<yade/lib/pyutil/doc_opts.hpp>
@@ -24,7 +25,8 @@
 	Vector3r mn(inf,inf,inf), mx(-inf,-inf,-inf);
 	FOREACH(const Vector3r& pt, pts){
 		Vector3r ptT=rot*pt;
-		mn=mn.cwise().min(ptT); mx=mx.cwise().max(ptT);
+		mn=mn.cwiseMin(ptT); 
+		mx=mx.cwiseMax(ptT);
 	}
 	halfSize=.5*(mx-mn);
 	center=.5*(mn+mx);

=== modified file 'py/pack/_packPredicates.cpp'
--- py/pack/_packPredicates.cpp	2012-04-13 16:27:00 +0000
+++ py/pack/_packPredicates.cpp	2013-03-07 18:28:01 +0000
@@ -1,9 +1,11 @@
 // 2009 © Václav Šmilauer <eudoxos@xxxxxxxx>
 #include<boost/python.hpp>
-#include<yade/extra/boost_python_len.hpp>
+#include<boost/python/object.hpp>
+#include<boost/version.hpp>
 #include<yade/lib/base/Logging.hpp>
 #include<yade/lib/base/Math.hpp>
 #include<yade/lib/pyutil/doc_opts.hpp>
+#include<iostream>
 
 namespace py=boost::python;
 using namespace std;
@@ -76,7 +78,12 @@
 	public:
 		PredicateUnion(const py::object _A, const py::object _B): PredicateBoolean(_A,_B){}
 		virtual bool operator()(const Vector3r& pt,Real pad) const {return obj2pred(A)(pt,pad)||obj2pred(B)(pt,pad);}
-		virtual py::tuple aabb() const { Vector3r minA,maxA,minB,maxB; ttuple2vvec(obj2pred(A).aabb(),minA,maxA); ttuple2vvec(obj2pred(B).aabb(),minB,maxB); return vvec2tuple(minA.cwise().min(minB),maxA.cwise().max(maxB));}
+		virtual py::tuple aabb() const { 
+			Vector3r minA,maxA,minB,maxB; 
+			ttuple2vvec(obj2pred(A).aabb(),minA,maxA); 
+			ttuple2vvec(obj2pred(B).aabb(),minB,maxB); 
+			return vvec2tuple(minA.cwiseMin(minB),maxA.cwiseMax(maxB));
+		}
 };
 PredicateUnion makeUnion(const py::object& A, const py::object& B){ return PredicateUnion(A,B);}
 
@@ -84,7 +91,12 @@
 	public:
 		PredicateIntersection(const py::object _A, const py::object _B): PredicateBoolean(_A,_B){}
 		virtual bool operator()(const Vector3r& pt,Real pad) const {return obj2pred(A)(pt,pad) && obj2pred(B)(pt,pad);}
-		virtual py::tuple aabb() const { Vector3r minA,maxA,minB,maxB; ttuple2vvec(obj2pred(A).aabb(),minA,maxA); ttuple2vvec(obj2pred(B).aabb(),minB,maxB); return vvec2tuple(minA.cwise().max(minB),maxA.cwise().min(maxB));}
+		virtual py::tuple aabb() const { 
+			Vector3r minA,maxA,minB,maxB; 
+			ttuple2vvec(obj2pred(A).aabb(),minA,maxA); 
+			ttuple2vvec(obj2pred(B).aabb(),minB,maxB); 
+			return vvec2tuple(minA.cwiseMax(minB),maxA.cwiseMin(maxB));
+		}
 };
 PredicateIntersection makeIntersection(const py::object& A, const py::object& B){ return PredicateIntersection(A,B);}
 
@@ -100,7 +112,12 @@
 	public:
 		PredicateSymmetricDifference(const py::object _A, const py::object _B): PredicateBoolean(_A,_B){}
 		virtual bool operator()(const Vector3r& pt,Real pad) const {bool inA=obj2pred(A)(pt,pad), inB=obj2pred(B)(pt,pad); return (inA && !inB) || (!inA && inB);}
-		virtual py::tuple aabb() const { Vector3r minA,maxA,minB,maxB; ttuple2vvec(obj2pred(A).aabb(),minA,maxA); ttuple2vvec(obj2pred(B).aabb(),minB,maxB); return vvec2tuple(minA.cwise().min(minB),maxA.cwise().max(maxB));}
+		virtual py::tuple aabb() const { 
+			Vector3r minA,maxA,minB,maxB; 
+			ttuple2vvec(obj2pred(A).aabb(),minA,maxA); 
+			ttuple2vvec(obj2pred(B).aabb(),minB,maxB); 
+			return vvec2tuple(minA.cwiseMin(minB),maxA.cwiseMax(maxB));
+		}
 };
 PredicateSymmetricDifference makeSymmetricDifference(const py::object& A, const py::object& B){ return PredicateSymmetricDifference(A,B);}
 
@@ -146,7 +163,10 @@
 		// bounding box
 		Vector3r vertices[8]={A,B,C,D,E,F,G,H};
 		mn=mx=vertices[0];
-		for(int i=1; i<8; i++){ mn=mn.cwise().min(vertices[i]); mx=mx.cwise().max(vertices[i]); }
+		for(int i=1; i<8; i++){ 
+			mn=mn.cwiseMin(vertices[i]); 
+			mx=mx.cwiseMax(vertices[i]); 
+		}
 	}
 	virtual bool operator()(const Vector3r& pt, Real pad=0.) const {
 		for(int i=0; i<6; i++) if((pt-pts[i]).dot(n[i])>-pad) return false;
@@ -174,7 +194,7 @@
 			sqrt((pow(A[1]-B[1],2)+pow(A[2]-B[2],2)))/ht,
 			sqrt((pow(A[0]-B[0],2)+pow(A[2]-B[2],2)))/ht,
 			sqrt((pow(A[0]-B[0],2)+pow(A[1]-B[1],2)))/ht);
-		Vector3r mn=A.cwise().min(B), mx=A.cwise().max(B);
+		Vector3r mn=A.cwiseMin(B), mx=A.cwiseMax(B);
 		return vvec2tuple((mn-radius*k).eval(),(mx+radius*k).eval());
 	}
 };
@@ -290,8 +310,8 @@
 {
 	GtsPoint *_p=GTS_POINT(vertex);
 	Vector3r p(_p->x,_p->y,_p->z);
-	bb->first=bb->first.cwise().min(p);
-	bb->second=bb->second.cwise().max(p);
+	bb->first=bb->first.cwiseMin(p);
+	bb->second=bb->second.cwiseMax(p);
 }
 
 /*

=== modified file 'py/pack/_packSpheres.cpp'
--- py/pack/_packSpheres.cpp	2012-07-23 16:06:38 +0000
+++ py/pack/_packSpheres.cpp	2013-01-22 14:15:20 +0000
@@ -24,7 +24,7 @@
 		.def("particleSD",&SpherePack::particleSD,(python::arg("minCorner"),python::arg("maxCorner"),python::arg("rMean"),python::arg("periodic")=false,python::arg("name"),python::arg("numSph"),python::arg("radii")=vector<Real>(),python::arg("passing")=vector<Real>(),python::arg("passingIsNotPercentageButCount")=false,python::arg("seed")=0),"Create random packing enclosed in box given by minCorner and maxCorner, containing numSph spheres. Returns number of created spheres, which can be < num if the packing is too tight. The computation is done according to the given psd.")
 		.def("particleSD2",&SpherePack::particleSD2,(python::arg("radii"),python::arg("passing"),python::arg("numSph"),python::arg("periodic")=false,python::arg("cloudPorosity")=.8,python::arg("seed")=0),"Create random packing following the given particle size distribution (radii and volume/mass passing for each fraction) and total number of particles *numSph*. The cloud size (periodic or aperiodic) is computed from the PSD and is always cubic.")
 		.def("particleSD_2d",&SpherePack::particleSD_2d,(python::arg("minCorner"),python::arg("maxCorner"),python::arg("rMean"),python::arg("periodic")=false,python::arg("name"),python::arg("numSph"),python::arg("radii")=vector<Real>(),python::arg("passing")=vector<Real>(),python::arg("passingIsNotPercentageButCount")=false,python::arg("seed")=0),"Create random packing on XY plane, defined by minCorner and maxCorner, containing numSph spheres. Returns number of created spheres, which can be < num if the packing is too tight. The computation is done according to the given psd.")
-		.def("makeClumpCloud",&SpherePack::makeClumpCloud,(python::arg("minCorner"),python::arg("maxCorner"),python::arg("clumps"),python::arg("periodic")=false,python::arg("num")=-1),"Create random loose packing of clumps within box given by *minCorner* and *maxCorner*. Clumps are selected with equal probability. At most *num* clumps will be positioned if *num* is positive; otherwise, as many clumps as possible will be put in space, until maximum number of attempts to place a new clump randomly is attained.")
+		.def("makeClumpCloud",&SpherePack::makeClumpCloud,(python::arg("minCorner"),python::arg("maxCorner"),python::arg("clumps"),python::arg("periodic")=false,python::arg("num")=-1,python::arg("seed")=0),"Create random loose packing of clumps within box given by *minCorner* and *maxCorner*. Clumps are selected with equal probability. At most *num* clumps will be positioned if *num* is positive; otherwise, as many clumps as possible will be put in space, until maximum number of attempts to place a new clump randomly is attained.\n:param seed: number used to initialize the random number generator.")
 		//
 		.def("aabb",&SpherePack::aabb_py,"Get axis-aligned bounding box coordinates, as 2 3-tuples.")
 		.def("dim",&SpherePack::dim,"Return dimensions of the packing in terms of aabb(), as a 3-tuple.")

=== modified file 'py/pack/pack.py'
--- py/pack/pack.py	2012-11-26 18:58:48 +0000
+++ py/pack/pack.py	2013-03-08 21:26:47 +0000
@@ -21,9 +21,12 @@
 from math import sqrt
 from yade import utils
 
-from miniEigen import *
 from yade.wrapper import *
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
 
 ## compatibility hack for python 2.5 (21/8/2009)
 ## can be safely removed at some point
@@ -83,9 +86,11 @@
     True
     >>> O.cell.refSize
     Vector3(5,5,5)
-    >>> O.cell.hSize
-    Matrix3(3.53553,-3.53553,0, 3.53553,3.53553,0, 0,0,5)
-  
+    """
+  #The following 2 lines do not work, because of accuaracy
+  #>>> O.cell.hSize
+  #Matrix3(3.53553,-3.53553,0, 3.53553,3.53553,0, 0,0,5)
+    """
   The current state (even if rotated) is taken as mechanically undeformed, i.e. with identity transformation:
   
     >>> O.cell.trsf
@@ -105,15 +110,14 @@
       return O.bodies.append([utils.sphere(rot*c,r,**kw) for c,r in self])
     else:
       standalone,clumps=self.getClumps()
-      idsOffset=len(O.bodies)
       ids=O.bodies.append([utils.sphere(rot*c,r,**kw) for c,r in self]) # append all spheres first
       clumpIds=[]
       userColor='color' in kw
       for clump in clumps:
-        clumpIds.append(O.bodies.clump([clump[0]+idsOffset,clump[1]+idsOffset])) # clump spheres with given ids together, creating the clump object as well
+        clumpIds.append(O.bodies.clump([ids[i] for i in clump])) # clump spheres with given ids together, creating the clump object as well
         # make all spheres within one clump a single color, unless color was specified by the user
         if not userColor:
-          for i in clump[1:]: O.bodies[i+idsOffset].shape.color=O.bodies[clump[0]+idsOffset].shape.color
+          for i in clump[1:]: O.bodies[ids[i]].shape.color=O.bodies[ids[clump[0]]].shape.color
       return ids+clumpIds
   
   SpherePack.toSimulation=SpherePack_toSimulation
@@ -444,7 +448,7 @@
 		#print x1,y1,z1,radius,rRelFuzz
 		O.materials.append(FrictMat(young=3e10,density=2400))
 		num=sp.makeCloud(Vector3().Zero,O.cell.refSize,radius,rRelFuzz,spheresInCell,True)
-		O.engines=[ForceResetter(),InsertionSortCollider([Bo1_Sphere_Aabb()],nBins=5,verletDist=.05*radius),InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[Law2_ScGeom_FrictPhys_CundallStrack()]),PeriIsoCompressor(charLen=2*radius,stresses=[-100e9,-1e8],maxUnbalanced=1e-2,doneHook='O.pause();',globalUpdateInt=5,keepProportions=True),NewtonIntegrator(damping=.6)]
+		O.engines=[ForceResetter(),InsertionSortCollider([Bo1_Sphere_Aabb()],verletDist=.05*radius),InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[Law2_ScGeom_FrictPhys_CundallStrack()]),PeriIsoCompressor(charLen=2*radius,stresses=[-100e9,-1e8],maxUnbalanced=1e-2,doneHook='O.pause();',globalUpdateInt=5,keepProportions=True),NewtonIntegrator(damping=.6)]
 		O.materials.append(FrictMat(young=30e9,frictionAngle=.5,poisson=.3,density=1e3))
 		for s in sp: O.bodies.append(utils.sphere(s[0],s[1]))
 		O.dt=utils.PWaveTimeStep()
@@ -493,7 +497,7 @@
 	#O.cell.refSize=initSize
 	O.cell.setBox(initSize)
 	sp.makeCloud(Vector3().Zero,O.cell.refSize,radius,rRelFuzz,-1,True)
-	O.engines=[ForceResetter(),InsertionSortCollider([Bo1_Sphere_Aabb()],nBins=2,verletDist=.05*radius),InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[Law2_ScGeom_FrictPhys_CundallStrack()]),PeriIsoCompressor(charLen=2*radius,stresses=[-100e9,-1e8],maxUnbalanced=1e-2,doneHook='O.pause();',globalUpdateInt=20,keepProportions=True),NewtonIntegrator(damping=.8)]
+	O.engines=[ForceResetter(),InsertionSortCollider([Bo1_Sphere_Aabb()],verletDist=.05*radius),InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[Law2_ScGeom_FrictPhys_CundallStrack()]),PeriIsoCompressor(charLen=2*radius,stresses=[-100e9,-1e8],maxUnbalanced=1e-2,doneHook='O.pause();',globalUpdateInt=20,keepProportions=True),NewtonIntegrator(damping=.8)]
 	O.materials.append(FrictMat(young=30e9,frictionAngle=.1,poisson=.3,density=1e3))
 	for s in sp: O.bodies.append(utils.sphere(s[0],s[1]))
 	O.dt=utils.PWaveTimeStep()

=== modified file 'py/plot.py'
--- py/plot.py	2012-09-08 01:19:45 +0000
+++ py/plot.py	2013-03-19 18:28:10 +0000
@@ -15,8 +15,11 @@
 try:
 	import Image
 except:
-	raise ImportError("PIL (python-imaging package) must be installed to use yade.plot")
-
+  try:
+    import PIL.Image
+  except:
+    import warnings
+    warnings.warn("PIL (python-imaging package) must be installed to use yade.plot")
 
 
 import matplotlib,os,time,math,itertools
@@ -35,7 +38,10 @@
 import yade.runtime
 if not yade.runtime.hasDisplay: matplotlib.use('Agg')
 
-from miniEigen import *
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
 
 #matplotlib.use('TkAgg')
 #matplotlib.use('GTKAgg')

=== modified file 'py/post2d.py'
--- py/post2d.py	2010-11-07 08:55:43 +0000
+++ py/post2d.py	2013-03-08 21:26:47 +0000
@@ -59,7 +59,11 @@
 
 """
 from yade.wrapper import *
-from miniEigen import *
+
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
 
 class Flatten:
 	"""Abstract class for converting 3d point into 2d. Used by post2d.data2d."""

=== modified file 'py/tests/clump.py'
--- py/tests/clump.py	2010-11-06 11:33:09 +0000
+++ py/tests/clump.py	2013-03-08 21:26:47 +0000
@@ -6,12 +6,16 @@
 import unittest
 import random
 from yade.wrapper import *
-from miniEigen import *
 from yade._customConverters import *
 from yade import utils
 from yade import *
 from math import *
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
+
 class TestSimpleClump(unittest.TestCase):
 	"Test things on a simple clump composed of 2 spheres."
 	def setUp(self):

=== modified file 'py/tests/cohesive-chain.py'
--- py/tests/cohesive-chain.py	2012-08-23 12:04:26 +0000
+++ py/tests/cohesive-chain.py	2013-03-08 21:26:47 +0000
@@ -8,12 +8,16 @@
 import unittest
 import random
 from yade.wrapper import *
-from miniEigen import *
 from yade._customConverters import *
 from yade import utils
 from yade import *
 from math import *
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
+
 class TestCohesiveChain(unittest.TestCase):
 	# prefix test names with PBC:
 	def setUp(self):

=== modified file 'py/tests/core.py'
--- py/tests/core.py	2012-09-05 18:09:18 +0000
+++ py/tests/core.py	2013-03-08 21:26:47 +0000
@@ -7,12 +7,16 @@
 import unittest
 import random
 from yade.wrapper import *
-from miniEigen import *
 from yade._customConverters import *
 from yade import utils
 from yade import *
 from math import *
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
+
 ## TODO tests
 class TestForce(unittest.TestCase): pass
 class TestTags(unittest.TestCase): pass 

=== modified file 'py/tests/engines.py'
--- py/tests/engines.py	2011-01-20 14:55:15 +0000
+++ py/tests/engines.py	2013-03-08 21:26:47 +0000
@@ -3,12 +3,15 @@
 import unittest
 import random
 from yade.wrapper import *
-from miniEigen import *
 from yade._customConverters import *
 from yade import utils
 from yade import *
 from math import *
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
 
 class TestKinematicEngines(unittest.TestCase):
 	def testKinematicEngines(self):

=== modified file 'py/tests/pbc.py'
--- py/tests/pbc.py	2011-09-20 10:58:18 +0000
+++ py/tests/pbc.py	2013-04-09 16:21:58 +0000
@@ -8,11 +8,14 @@
 import unittest
 import random,math
 from yade.wrapper import *
-from miniEigen import *
 from yade._customConverters import *
 from yade import utils
 from yade import *
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
 
 class TestPBC(unittest.TestCase):
 	# prefix test names with PBC: 
@@ -31,17 +34,16 @@
 		O.cell.velGrad=Matrix3(0,0,0, 0,0,0, 0,0,-1)
 		O.dt=0 # do not change positions with dt=0 in NewtonIntegrator, but still update velocities from velGrad
 	def testVelGrad(self):
-		'PBC: velGrad changes hSize but not hSize0, accumulates in trsf'
+		'PBC: velGrad changes hSize, accumulates in trsf'
 		O.dt=1e-3
 		hSize,trsf=O.cell.hSize,Matrix3.Identity
 		hSize0=hSize
+		O.step()
 		for i in range(0,10):
 			O.step(); hSize+=O.dt*O.cell.velGrad*hSize; trsf+=O.dt*O.cell.velGrad*trsf
 		for i in range(0,len(O.cell.hSize)):
 			self.assertAlmostEqual(hSize[i],O.cell.hSize[i])
 			self.assertAlmostEqual(trsf[i],O.cell.trsf[i])
-			# ?? should work
-			#self.assertAlmostEqual(hSize0[i],O.cell.hSize0[i])
 	def testTrsfChange(self):
 		'PBC: chaing trsf changes hSize0, but does not modify hSize'
 		O.dt=1e-2
@@ -64,7 +66,7 @@
 		self.assertAlmostEqual(s1.vel[2],self.initVel[2]+self.initPos[2]*O.cell.velGrad[2,2])
 	def testScGeomIncidentVelocity(self):
 		"PBC: ScGeom computes incident velocity correctly"
-		O.step()
+		O.run(2,1)
 		O.engines=[InteractionLoop([Ig2_Sphere_Sphere_ScGeom()],[Ip2_FrictMat_FrictMat_FrictPhys()],[])]
 		i=utils.createInteraction(0,1)
 		self.assertEqual(self.initVel,i.geom.incidentVel(i,avoidGranularRatcheting=True))

=== modified file 'py/tests/wrapper.py'
--- py/tests/wrapper.py	2012-06-28 19:34:29 +0000
+++ py/tests/wrapper.py	2013-03-08 21:26:47 +0000
@@ -8,12 +8,16 @@
 
 import unittest
 from yade.wrapper import *
-from miniEigen import *
 from yade._customConverters import *
 from math import *
 from yade import system
 from yade import *
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
+
 allClasses=system.childClasses('Serializable')
 
 class TestObjectInstantiation(unittest.TestCase):

=== modified file 'py/timing.py'
--- py/timing.py	2010-09-27 17:47:59 +0000
+++ py/timing.py	2013-04-24 16:19:28 +0000
@@ -45,7 +45,7 @@
 	for d in deltas.data:
 		print _formatLine(d[0],d[1],d[2],totalTime,level); ret+=1
 	if len(deltas.data)>1:
-		print _formatLine('TOTAL',deltaTime,-1,totalTime,level); ret+=1
+		print _formatLine('TOTAL',deltaTime,sum(d[2] for d in deltas.data),totalTime,level); ret+=1
 	return ret
 
 def _engines_stats(engines,totalTime,level):
@@ -54,7 +54,7 @@
 		if not isinstance(e,Functor): print _formatLine(u'"'+e.label+'"' if e.label else e.__class__.__name__,e.execTime,e.execCount,totalTime,level); lines+=1; hereLines+=1
 		if e.timingDeltas: 
 			if isinstance(e,Functor):
-				print _formatLine(e.__class__.__name__,-1,-1,-1,level); lines+=1; hereLines+=1
+				print _formatLine(e.__class__.__name__,sum(d[1] for d in e.timingDeltas.data),sum(d[2] for d in e.timingDeltas.data),totalTime,level); lines+=1; hereLines+=1
 				execTime=sum([d[1] for d in e.timingDeltas.data])
 			else: execTime=e.execTime
 			lines+=_delta_stats(e.timingDeltas,execTime,level+1)
@@ -64,7 +64,7 @@
 			lines+=_engines_stats(e.physDispatcher.functors,e.execTime,level+1)
 			lines+=_engines_stats(e.lawDispatcher.functors,e.execTime,level+1)
 		elif isinstance(e,ParallelEngine): lines+=_engines_stats(e.slave,e.execTime,level+1)
-	if hereLines>1:
+	if hereLines>1 and not isinstance(e,Functor):
 		print _formatLine('TOTAL',totalTime,-1,totalTime,level); lines+=1
 	return lines
 
@@ -73,27 +73,50 @@
 
 	.. code-block:: none
 
-		Name                                     Count                 Time        Rel. time
-		------------------------------------------------------------------------------------
-		ForceResetter                        400               9449μs            0.01%      
-		BoundingVolumeMetaEngine             400            1171770μs            1.15%      
-		PersistentSAPCollider                400            9433093μs            9.24%      
-		InteractionGeometryMetaEngine        400           15177607μs           14.87%      
-		InteractionPhysicsMetaEngine         400            9518738μs            9.33%      
-		ConstitutiveLawDispatcher            400           64810867μs           63.49%      
-		  ef2_Spheres_Brefcom_BrefcomLaw                                                    
-			 setup                            4926145            7649131μs           15.25%  
-			 geom                             4926145           23216292μs           46.28%  
-			 material                         4926145            8595686μs           17.14%  
-			 rest                             4926145           10700007μs           21.33%  
-			 TOTAL                                              50161117μs          100.00%  
-		"damper"                             400            1866816μs            1.83%      
-		"strainer"                           400              21589μs            0.02%      
-		"plotDataCollector"                  160              64284μs            0.06%      
-		"damageChecker"                        9               3272μs            0.00%      
-		TOTAL                                             102077490μs          100.00%      
+		Name                                                    Count                 Time            Rel. time
+		-------------------------------------------------------------------------------------------------------
+		ForceResetter                                       102               2150us                0.02%      
+		"collider"                                            5              64200us                0.60%      
+		InteractionLoop                                     102           10571887us               98.49%      
+		"combEngine"                                        102               8362us                0.08%      
+		"newton"                                            102              73166us                0.68%      
+		"cpmStateUpdater"                                     1               9605us                0.09%      
+		PyRunner                                              1                136us                0.00%      
+		"plotDataCollector"                                   1                291us                0.00%      
+		TOTAL                                                             10733564us              100.00%
+
+
+	sample output (compiled with -DCMAKE_CXX_FLAGS="-DUSE_TIMING_DELTAS" option):
+
+	.. code-block:: none
+
+		Name                                                    Count                 Time            Rel. time
+		-------------------------------------------------------------------------------------------------------
+		ForceResetter                                       102               2150us                0.02%      
+		"collider"                                            5              64200us                0.60%      
+		InteractionLoop                                     102           10571887us               98.49%      
+		  Ig2_Sphere_Sphere_ScGeom                        1222186            1723168us               16.30%    
+		    Ig2_Sphere_Sphere_ScGeom                        1222186            1723168us              100.00%  
+		  Ig2_Facet_Sphere_ScGeom                             753               1157us                0.01%    
+		    Ig2_Facet_Sphere_ScGeom                             753               1157us              100.00%  
+		  Ip2_CpmMat_CpmMat_CpmPhys                         11712              26015us                0.25%    
+		    end of Ip2_CpmPhys                                11712              26015us              100.00%  
+		  Ip2_FrictMat_CpmMat_FrictPhys                         0                  0us                0.00%    
+		  Law2_ScGeom_CpmPhys_Cpm                         3583872            4819289us               45.59%    
+		    GO A                                            1194624            1423738us               29.54%  
+		    GO B                                            1194624            1801250us               37.38%  
+		    rest                                            1194624            1594300us               33.08%  
+		    TOTAL                                           3583872            4819289us              100.00%  
+		  Law2_ScGeom_FrictPhys_CundallStrack                   0                  0us                0.00%    
+		"combEngine"                                        102               8362us                0.08%      
+		"newton"                                            102              73166us                0.68%      
+		"cpmStateUpdater"                                     1               9605us                0.09%      
+		PyRunner                                              1                136us                0.00%      
+		"plotDataCollector"                                   1                291us                0.00%      
+		TOTAL                                                             10733564us              100.00%
 
 	"""
+
 	print 'Name'.ljust(_statCols['label'])+' '+'Count'.rjust(_statCols['count'])+' '+'Time'.rjust(_statCols['time'])+' '+'Rel. time'.rjust(_statCols['relTime'])
 	print '-'*(sum([_statCols[k] for k in _statCols])+len(_statCols)-1)
 	_engines_stats(O.engines,sum([e.execTime for e in O.engines]),0)

=== modified file 'py/utils.py'
--- py/utils.py	2012-11-22 14:44:53 +0000
+++ py/utils.py	2013-03-21 13:38:27 +0000
@@ -12,12 +12,16 @@
 import math,random,doctest,geom,numpy
 from yade import *
 from yade.wrapper import *
-from miniEigen import *
 try: # use psyco if available
 	import psyco
 	psyco.full()
 except ImportError: pass
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
+
 
 # c++ implementations for performance reasons
 from yade._utils import *
@@ -27,22 +31,30 @@
 
 	For example, variables *a*, *b* and *c* are defined. To save them, use::
 
-		>>> from yade import utils
-		>>> utils.saveVars('something',a=1,b=2,c=3)
+		>>> saveVars('something',a=1,b=2,c=3)
 		>>> from yade.params.something import *
 		>>> a,b,c
 		(1, 2, 3)
 
 	those variables will be save in the .xml file, when the simulation itself is saved. To recover those variables once the .xml is loaded again, use
 
-		>>> utils.loadVars('something')
+		>>> loadVars('something')
 
 	and they will be defined in the yade.params.\ *mark* module. The *loadNow* parameter calls :yref:`yade.utils.loadVars` after saving automatically.
+	
+	If 'something' already exists, given variables will be inserted.
 	"""
 	import cPickle
-	Omega().tags['pickledPythonVariablesDictionary'+mark]=cPickle.dumps(kw)
+	try: 
+		d=cPickle.loads(Omega().tags['pickledPythonVariablesDictionary'+mark])	#load dictionary d
+		for key in kw.keys():
+			d[key]=kw[key]							#insert new variables into d
+	except KeyError: 
+		d = kw
+	Omega().tags['pickledPythonVariablesDictionary'+mark]=cPickle.dumps(d)
 	if loadNow: loadVars(mark)
 
+
 def loadVars(mark=None):
 	"""Load variables from :yref:`yade.utils.saveVars`, which are saved inside the simulation.
 	If ``mark==None``, all save variables are loaded. Otherwise only those with
@@ -203,7 +215,7 @@
 	b.mask=mask
 	return b
 
-def box(center,extents,orientation=[1,0,0,0],dynamic=None,fixed=False,wire=False,color=None,highlight=False,material=-1,mask=1):
+def box(center,extents,orientation=Quaternion(1,0,0,0),dynamic=None,fixed=False,wire=False,color=None,highlight=False,material=-1,mask=1):
 	"""Create box (cuboid) with given parameters.
 
 	:param Vector3 extents: half-sizes along x,y,z axes
@@ -214,6 +226,7 @@
 	V=8*extents[0]*extents[1]*extents[2]
 	geomInert=Vector3(4*(extents[1]**2+extents[2]**2),4*(extents[0]**2+extents[2]**2),4*(extents[0]**2+extents[1]**2))
 	_commonBodySetup(b,V,geomInert,material,pos=center,dynamic=dynamic,fixed=fixed)
+	b.state.ori=orientation
 	b.mask=mask
 	b.aspherical=True
 	return b
@@ -261,22 +274,26 @@
 	b=Body()
 	b.shape=GridConnection(radius=radius,color=color if color else randomColor(),wire=wire,highlight=highlight)
 	sph1=O.bodies[id1] ; sph2=O.bodies[id2]
+	i=createInteraction(id1,id2)
+	nodeMat=sph1.material
 	b.shape.node1=sph1 ; b.shape.node2=sph2
 	sph1.shape.addConnection(b) ; sph2.shape.addConnection(b)
-	segt=sph2.state.pos - sph1.state.pos
+	if(O.periodic):
+		if(cellDist!=None):
+			i.cellDist=cellDist
+		segt=sph2.state.pos + O.cell.hSize*i.cellDist - sph1.state.pos
+	else: segt=sph2.state.pos - sph1.state.pos
 	L=segt.norm()
 	V=0.5*L*math.pi*radius**2
 	geomInert=(2./5.)*V*radius**2
-	_commonBodySetup(b,V,Vector3(0.,0.,0.),material,pos=sph1.state.pos,dynamic=False,fixed=True)
-	sph1.state.mass = sph1.state.mass + V*b.material.density
-	sph2.state.mass = sph2.state.mass + V*b.material.density
-	for i in [0,1,2]:
-		sph1.state.inertia[i] = sph1.state.inertia[i] + geomInert*b.material.density
-		sph2.state.inertia[i] = sph2.state.inertia[i] + geomInert*b.material.density
+	_commonBodySetup(b,V,Vector3(geomInert,geomInert,geomInert),material,pos=sph1.state.pos,dynamic=False,fixed=True)
+	sph1.state.mass = sph1.state.mass + V*nodeMat.density
+	sph2.state.mass = sph2.state.mass + V*nodeMat.density
+	for k in [0,1,2]:
+		sph1.state.inertia[k] = sph1.state.inertia[k] + geomInert*nodeMat.density
+		sph2.state.inertia[k] = sph2.state.inertia[k] + geomInert*nodeMat.density
 	b.aspherical=False
-	i=createInteraction(id1,id2)
 	if O.periodic:
-		if(cellDist!=None):i.cellDist=cellDist
 		i.phys.unp= -(sph2.state.pos + O.cell.hSize*i.cellDist - sph1.state.pos).norm() + sph1.shape.radius + sph2.shape.radius
 		b.shape.periodic=True
 		b.shape.cellDist=i.cellDist
@@ -284,11 +301,11 @@
 		i.phys.unp= -(sph2.state.pos - sph1.state.pos).norm() + sph1.shape.radius + sph2.shape.radius	
 	i.geom.connectionBody=b
 	I=math.pi*(2.*radius)**4/64.
-	E=sph1.material.young
+	E=nodeMat.young
 	i.phys.kn=E*math.pi*(radius**2)/L
 	i.phys.kr=2.*E*I/L
 	i.phys.ks=12.*E*I/(L**3)
-	G=E/(2.*(1+sph1.material.poisson))
+	G=E/(2.*(1+nodeMat.poisson))
 	i.phys.ktw=2.*I*G/L
 	b.mask=mask
 	return b
@@ -412,12 +429,13 @@
 		color=(random.random(),random.random(),random.random())
 		if b.dynamic or not onlyDynamic: b.shape.color=color
 
-def avgNumInteractions(cutoff=0.,skipFree=False):
+def avgNumInteractions(cutoff=0.,skipFree=False,considerClumps=False):
 	r"""Return average numer of interactions per particle, also known as *coordination number* $Z$. This number is defined as
 
 	.. math:: Z=2C/N
 
-	where $C$ is number of contacts and $N$ is number of particles.
+	where $C$ is number of contacts and $N$ is number of particles. When clumps are present, number of particles is the sum of standalone spheres plus the sum of clumps.
+	Clumps are considered in the calculation if cutoff != 0 or skipFree = True. If cutoff=0 (default) and skipFree=False (default) one needs to set considerClumps=True to consider clumps in the calculation.
 
 	With *skipFree*, particles not contributing to stable state of the packing are skipped, following equation (8) given in [Thornton2000]_:
 
@@ -425,21 +443,21 @@
 
 	:param cutoff: cut some relative part of the sample's bounding box away.
 	:param skipFree: see above.
+	:param considerClumps: also consider clumps if cutoff=0 and skipFree=False; for further explanation see above.
 	
 """
-	if cutoff==0 and not skipFree: return 2*O.interactions.countReal()*1./len(O.bodies)
+	if cutoff==0 and not skipFree and not considerClumps: return 2*O.interactions.countReal()*1./len(O.bodies)
 	else:
 		nums,counts=bodyNumInteractionsHistogram(aabbExtrema(cutoff))
 		## CC is 2*C
 		CC=sum([nums[i]*counts[i] for i in range(len(nums))]); N=sum(counts)
-		if not skipFree: return CC*1./N
+		if not skipFree: return CC*1./N if N>0 else float('nan')
 		## find bins with 0 and 1 spheres
 		N0=0 if (0 not in nums) else counts[nums.index(0)]
 		N1=0 if (1 not in nums) else counts[nums.index(1)]
 		NN=N-N0-N1
 		return (CC-N1)*1./NN if NN>0 else float('nan')
 
-
 def plotNumInteractionsHistogram(cutoff=0.):
 	"Plot histogram with number of interactions per body, optionally cutting away *cutoff* relative axis-aligned box from specimen margin."
 	nums,counts=bodyNumInteractionsHistogram(aabbExtrema(cutoff))
@@ -883,3 +901,26 @@
 			binsProc[i] = binsSumCum[i]/binsSumCum[len(binsSumCum)-1]
 			i+=1
 	return binsSizes, binsProc, binsSumCum
+
+class clumpTemplate:
+	"""Create a clump template by a list of relative radii and a list of relative positions. Both lists must have the same length.
+	
+	:param [float,float,...] relRadii: list of relative radii (minimum length = 2)
+	:param [Vector3,Vector3,...] relPositions: list of relative positions (minimum length = 2)
+	
+	"""
+	def __init__(self,relRadii=[],relPositions=[[],[]]):
+		if (len(relRadii) != len(relPositions)):
+			raise ValueError("Given lists must have same length! Given lists does not match clump template structure.");
+		if (len(relRadii) < 2):
+			raise ValueError("One or more of given lists for relative radii have length < 2! Given lists does not match clump template structure.");
+		for ii in range(0,len(relPositions)):
+			if len(relPositions[ii]) != 3:
+				raise ValueError("One or more of given lists for relative positions do not have length of 3! Given lists does not match clump template structure.");
+			for jj in range(ii,len(relPositions)):
+				if ii != jj:
+					if (relPositions[ii] == relPositions[jj]): 
+						raise ValueError("Two or more of given lists for relative positions are equal! Given lists does not match clump template structure.");
+		self.numCM = len(relRadii)
+		self.relRadii = relRadii
+		self.relPositions = relPositions

=== modified file 'py/wrapper/yadeWrapper.cpp'
--- py/wrapper/yadeWrapper.cpp	2012-09-17 17:05:49 +0000
+++ py/wrapper/yadeWrapper.cpp	2013-04-17 07:39:24 +0000
@@ -46,6 +46,7 @@
 
 // #include<yade/pkg/dem/Shop.hpp>
 #include<yade/core/Clump.hpp>
+#include <yade/pkg/common/Sphere.hpp>
 
 #if BOOST_VERSION>=104700
 	#include<boost/math/special_functions/nonfinite_num_facets.hpp>
@@ -53,6 +54,12 @@
 	#include<boost/math/nonfinite_num_facets.hpp>
 #endif
 
+#include <boost/random/linear_congruential.hpp>
+#include <boost/random/uniform_real.hpp>
+#include <boost/random/variate_generator.hpp>
+
+#include<yade/core/Timing.hpp>
+
 #include<locale>
 #include<boost/archive/codecvt_null.hpp>
 
@@ -62,7 +69,8 @@
 
 #include<yade/lib/serialization/ObjectIO.hpp>
 
-#include<yade/extra/boost_python_len.hpp>
+#include<boost/python/object.hpp>
+#include<boost/version.hpp>
 
 /*
 Python normally iterates over object it is has __getitem__ and __len__, which BodyContainer does.
@@ -81,6 +89,14 @@
 };
 
 class pyBodyContainer{
+	private:
+		void checkClump(shared_ptr<Body> b){
+			if (!(b->isClump())){
+				PyErr_SetString(PyExc_TypeError,("Error: Body"+lexical_cast<string>(b->getId())+" is not a clump.").c_str()); 
+				python::throw_error_already_set();
+			}
+		}
+		typedef std::map<Body::id_t,Se3r> MemberMap;
 	public:
 	const shared_ptr<BodyContainer> proxee;
 	pyBodyIterator pyIter(){return pyBodyIterator(proxee);}
@@ -142,6 +158,326 @@
 		// clump them together (the clump fcn) and return
 		return python::make_tuple(clump(ids),ids);
 	}
+	void addToClump(Body::id_t bid, Body::id_t cid){
+		Scene* scene(Omega::instance().getScene().get());	// get scene
+		shared_ptr<Body> bp = Body::byId(bid,scene);		// get body pointer
+		shared_ptr<Body> clp = Body::byId(cid,scene);		// get clump pointer
+		checkClump(clp);
+		if (bp->isClump()){
+			if (bp == clp) {PyErr_Warn(PyExc_UserWarning,("Warning: Body "+lexical_cast<string>(bid)+" and clump "+lexical_cast<string>(cid)+" are the same bodies. Body was not added.").c_str()); return;}
+			Clump::add(clp,bp);//add clump bid to clump cid
+			Clump::updateProperties(clp,/*intersecting*/false);
+			proxee->erase(bid);//erase old clump
+			return;
+		}
+		else if (bp->isClumpMember()){
+			Body::id_t bpClumpId = bp->clumpId;
+			shared_ptr<Body> bpClumpPointer = Body::byId(bpClumpId,scene);
+			if (bpClumpPointer == clp) {PyErr_Warn(PyExc_UserWarning,("Warning: Body "+lexical_cast<string>(bid)+" is already a clump member of clump "+lexical_cast<string>(cid)+". Body was not added.").c_str()); return;} 
+			Clump::add(clp,bpClumpPointer);//add clump bpClumpId to clump cid
+			Clump::updateProperties(clp,/*intersecting*/false);
+			proxee->erase(bpClumpId);//erase old clump
+			return;
+		}
+		else {Clump::add(clp,bp); Clump::updateProperties(clp,/*intersecting*/false);}// bp must be a standalone!
+	}
+	void releaseFromClump(Body::id_t bid, Body::id_t cid){
+		Scene* scene(Omega::instance().getScene().get());	// get scene
+		shared_ptr<Body> bp = Body::byId(bid,scene);		// get body pointer
+		shared_ptr<Body> clp = Body::byId(cid,scene);		// get clump pointer
+		checkClump(clp);
+		if (bp->isClumpMember()){
+			Body::id_t bpClumpId = bp->clumpId;
+			if (cid == bpClumpId){
+				const shared_ptr<Clump>& clump=YADE_PTR_CAST<Clump>(clp->shape);
+				std::map<Body::id_t,Se3r>& members = clump->members;
+				if (members.size() == 2) {PyErr_Warn(PyExc_UserWarning,("Warning: Body "+lexical_cast<string>(bid)+" not released from clump "+lexical_cast<string>(cid)+", because number of clump members would get < 2!").c_str()); return;}
+				Clump::del(clp,bp);//release bid from cid
+				Clump::updateProperties(clp,/*intersecting*/false);
+			} else { PyErr_Warn(PyExc_UserWarning,("Warning: Body "+lexical_cast<string>(bid)+" must be a clump member of clump "+lexical_cast<string>(cid)+". Body was not released.").c_str()); return;}
+		} else { PyErr_Warn(PyExc_UserWarning,("Warning: Body "+lexical_cast<string>(bid)+" is not a clump member. Body was not released.").c_str()); return;}
+	}
+	python::list replaceByClumps(python::list ctList, vector<Real> amounts){
+		python::list ret;
+		Real checkSum = 0.0;
+		FOREACH(Real amount, amounts) {
+			if (amount < 0.0) {
+				PyErr_SetString(PyExc_ValueError,("Error: One or more of given amounts are negative!")); 
+				python::throw_error_already_set();
+			}
+			else checkSum += amount;
+		}
+		if (checkSum > 1.0){
+			PyErr_SetString(PyExc_ValueError,("Error: Sum of amounts "+lexical_cast<string>(checkSum)+" should not be bigger than 1.0!").c_str()); 
+			python::throw_error_already_set();
+		}
+		if (python::len(ctList) != (unsigned) amounts.size()) {//avoid unsigned comparison warning
+			PyErr_SetString(PyExc_ValueError,("Error: Length of amounts list ("+lexical_cast<string>(amounts.size())+") differs from length of template list ("+lexical_cast<string>(python::len(ctList))+").").c_str()); 
+			python::throw_error_already_set();
+		}
+		//set a random generator (code copied from pkg/dem/SpherePack.cpp):
+		static boost::minstd_rand randGen((int)TimingInfo::getNow(/* get the number even if timing is disabled globally */ true));
+		typedef boost::variate_generator<boost::minstd_rand&, boost::uniform_real<> > UniRandGen;
+		static UniRandGen rndUnit(randGen,boost::uniform_real<>(-1,1));
+		
+		//get number of spherical particles and a list of all spheres:
+		vector<shared_ptr<Body> > sphereList;
+		shared_ptr<Sphere> sph (new Sphere);
+		int Sph_Index = sph->getClassIndexStatic();
+		FOREACH(const shared_ptr<Body>& b, *proxee) if ( (b->shape->getClassIndex() == Sph_Index) && (b->isStandalone()) ) sphereList.push_back(b);
+		int num = sphereList.size();
+		
+		//loop over templates:
+		int numSphereList = num, numTemplates = amounts.size();
+		for (int ii = 0; ii < numTemplates; ii++) {
+			//ctList: [<ct1>,<ct2>, ...] = [<int,[double,double, ... ],[Vector3r,Vector3r, ...]>,<int,[double,double, ... ],[Vector3r,Vector3r, ...]>, ...]
+			//ct: <len(relRadList),relRadList,relPosList> = <int,[double,double, ... ],[Vector3r,Vector3r, ...]> (python objects)
+			//relRadList: [relRad1,relRad2, ...] (list of doubles)
+			//relPosList: [relPos1,relPos2, ...] (list of vectors)
+			
+			//extract attributes from python objects:
+			python::object ctTmp = ctList[ii];
+			int numCM = python::extract<int>(ctTmp.attr("numCM"))();
+			python::list relRadListTmp = python::extract<python::list>(ctTmp.attr("relRadii"))();
+			python::list relPosListTmp = python::extract<python::list>(ctTmp.attr("relPositions"))();
+			
+			//get relative radii and positions; calc. volumes; get balance point:
+			vector<Real> relRadTmp(numCM), relVolTmp(numCM);
+			vector<Vector3r> relPosTmp(numCM);
+			Vector3r relPosTmpMean = Vector3r::Zero();
+			for (int jj = 0; jj < numCM; jj++) {
+				relRadTmp[jj] = python::extract<Real>(relRadListTmp[jj])();
+				relVolTmp[jj] = (4./3.)*Mathr::PI*pow(relRadTmp[jj],3.);
+				relPosTmp[jj] = python::extract<Vector3r>(relPosListTmp[jj])();
+				relPosTmpMean += relPosTmp[jj];
+			}
+			relPosTmpMean /= numCM;//balance point
+
+			//check for overlaps and correct volumes (-= volume of spherical caps):
+			Real distCMTmp, overlapTmp, hCapjj, hCapkk;
+			for (int jj = 0; jj < numCM; jj++) {
+				for (int kk = jj; kk < numCM; kk++) {
+					if (jj != kk) {
+						distCMTmp = (relPosTmp[jj] - relPosTmp[kk]).norm(); //distance between two spheres
+						overlapTmp = (relRadTmp[jj] + relRadTmp[kk]) - distCMTmp;//positive if overlapping ...
+						if (overlapTmp > 0.0) {//calculation of overlapping spheres, see http://mathworld.wolfram.com/Sphere-SphereIntersection.html
+							hCapjj = relRadTmp[jj] - (distCMTmp*distCMTmp - relRadTmp[kk]*relRadTmp[kk] + relRadTmp[jj]*relRadTmp[jj])/(2*distCMTmp);
+							hCapkk = relRadTmp[kk] - (distCMTmp*distCMTmp - relRadTmp[jj]*relRadTmp[jj] + relRadTmp[kk]*relRadTmp[kk])/(2*distCMTmp);
+							//calculation of spherical cap, see http://en.wikipedia.org/wiki/Spherical_cap
+							relVolTmp[jj] -= (1./3.)*Mathr::PI*hCapjj*hCapjj*(3.*relRadTmp[jj] - hCapjj);// correct relative volumes
+							relVolTmp[kk] -= (1./3.)*Mathr::PI*hCapkk*hCapkk*(3.*relRadTmp[kk] - hCapkk);
+						}
+					}
+				}
+			}
+			
+			//get relative volume of the clump:
+			Real relVolSumTmp = 0.0;
+			for (int jj = 0; jj < numCM; jj++) relVolSumTmp += relVolTmp[jj];
+			
+			//get pointer lists of spheres, that should be replaced:
+			int numReplaceTmp = round(num*amounts[ii]);
+			vector<shared_ptr<Body> > bpListTmp(numReplaceTmp);
+			int a = 0, c = 0;//counters
+			vector<int> posTmp;
+			FOREACH (const shared_ptr<Body>& b, sphereList) {
+				if (c == a*numSphereList/numReplaceTmp) {
+					bpListTmp[a] = b; a++;
+					posTmp.push_back(c);//remember position in sphereList
+				} c++;
+			}
+			for (int jj = 0; jj < a; jj++) {
+				sphereList.erase(sphereList.begin()+posTmp[jj]-jj);//remove bodies from sphereList, that were already found
+				numSphereList--;
+			}
+			
+			//adapt position- and radii-informations and replace spheres from bpListTmp by clumps:
+			FOREACH (const shared_ptr<Body>& b, bpListTmp) {
+				//get sphere, that should be replaced:
+				const Sphere* sphere = YADE_CAST<Sphere*> (b->shape.get());
+				shared_ptr<Material> matTmp = b->material;
+				
+				//get a random rotation quaternion:
+				Quaternionr randAxisTmp = (Quaternionr) AngleAxisr(2*Mathr::PI*rndUnit(),Vector3r(rndUnit(),rndUnit(),rndUnit()));
+				randAxisTmp.normalize();
+				
+				//convert geometries in global coordinates (scaling):
+				Real scalingFactorVolume = ((4./3.)*Mathr::PI*pow(sphere->radius,3.))/relVolSumTmp;
+				Real scalingFactor1D = pow(scalingFactorVolume,1./3.);//=((vol. sphere)/(relative clump volume))^(1/3)
+				vector<Vector3r> newPosTmp(numCM);
+				vector<Real> newRadTmp(numCM);
+				vector<Body::id_t> idsTmp(numCM);
+				for (int jj = 0; jj < numCM; jj++) {
+					newPosTmp[jj] = relPosTmp[jj] - relPosTmpMean;	//shift position, to get balance point at (0,0,0)
+					newPosTmp[jj] = randAxisTmp*newPosTmp[jj];	//rotate around balance point
+					newRadTmp[jj] = relRadTmp[jj] * scalingFactor1D;//scale radii
+					newPosTmp[jj] = newPosTmp[jj] * scalingFactor1D;//scale position
+					newPosTmp[jj] += b->state->pos;			//translate new position to spheres center
+					
+					//create spheres:
+					shared_ptr<Body> newSphere = shared_ptr<Body>(new Body());
+					newSphere->state->blockedDOFs = State::DOF_NONE;
+					newSphere->state->mass = scalingFactorVolume*relVolTmp[jj]*matTmp->density;//vol. corrected mass for clump members
+					Real inertiaTmp = 2.0/5.0*newSphere->state->mass*newRadTmp[jj]*newRadTmp[jj];
+					newSphere->state->inertia	= Vector3r(inertiaTmp,inertiaTmp,inertiaTmp);
+					newSphere->state->pos = newPosTmp[jj];
+					newSphere->material = matTmp;
+					
+					shared_ptr<Sphere> sphereTmp = shared_ptr<Sphere>(new Sphere());
+					sphereTmp->radius = newRadTmp[jj];
+					sphereTmp->color = Vector3r(Mathr::UnitRandom(),Mathr::UnitRandom(),Mathr::UnitRandom());
+					sphereTmp->color.normalize();
+					newSphere->shape = sphereTmp;
+					
+					shared_ptr<Aabb> aabbTmp = shared_ptr<Aabb>(new Aabb());
+					aabbTmp->color = Vector3r(0,1,0);
+					newSphere->bound = aabbTmp;
+					proxee->insert(newSphere);
+					LOG_DEBUG("New body (sphere) "<<newSphere->id<<" added.");
+					idsTmp[jj] = newSphere->id;
+				}
+				Body::id_t newClumpId = clump(idsTmp);
+				ret.append(python::make_tuple(newClumpId,idsTmp));
+				erase(b->id);
+			}
+		}
+		return ret;
+	}
+	Real getClumpVolume(const shared_ptr<Body>& b, int numTries){//algorithm for estimation of clump volumes
+		checkClump(b);
+		Scene* scene(Omega::instance().getScene().get());	// get scene
+		shared_ptr<Sphere> sph (new Sphere);
+		int Sph_Index = sph->getClassIndexStatic();		// get sphere index for checking if bodies are spheres
+		//get boundaries of clump:
+		const shared_ptr<Clump>& clump=YADE_PTR_CAST<Clump>(b->shape);
+		std::map<Body::id_t,Se3r>& members = clump->members;
+		Real xmax = -1e10;
+		Real ymax = xmax;
+		Real zmax = xmax;
+		Real xmin = 1e10;
+		Real ymin = xmin;
+		Real zmin = xmin;
+		FOREACH(MemberMap::value_type& mm, members){
+			const Body::id_t& memberId=mm.first;
+			const shared_ptr<Body>& member=Body::byId(memberId,scene);
+			assert(member->isClumpMember());
+			if (member->shape->getClassIndex() ==  Sph_Index){//clump member should be a sphere
+				const Sphere* sphere = YADE_CAST<Sphere*> (member->shape.get());
+				xmax = max(member->state->pos[0] + sphere->radius, xmax);
+				ymax = max(member->state->pos[1] + sphere->radius, ymax);
+				zmax = max(member->state->pos[2] + sphere->radius, zmax);
+				xmin = min(member->state->pos[0] - sphere->radius, xmin);
+				ymin = min(member->state->pos[1] - sphere->radius, ymin);
+				zmin = min(member->state->pos[2] - sphere->radius, zmin);
+			}
+			else {PyErr_Warn(PyExc_UserWarning,("Warning: getClumpVolume method detected, that clump with id "+lexical_cast<string>(b->getId())+" has non-spherical members.").c_str()); return 0;}
+		}
+		//generate regular grid points and check if point is inside or outside of clump:
+		Vector3r gridPoint;
+		int c_in = 0;
+		int numPoints1D = ceil(pow(numTries,1./3.));
+		for (int ii = 0; ii < numPoints1D; ii++){
+			for (int jj = 0; jj < numPoints1D; jj++){
+				for (int kk = 0; kk < numPoints1D; kk++){
+					bool isInside = false;
+					gridPoint = Vector3r(xmin + (xmax-xmin)*(ii+.5)/numPoints1D,ymin + (ymax-ymin)*(jj+.5)/numPoints1D,zmin + (zmax-zmin)*(kk+.5)/numPoints1D);
+					FOREACH(MemberMap::value_type& mm, members){
+						const Body::id_t& memberId=mm.first;
+						const shared_ptr<Body>& member=Body::byId(memberId,scene);
+						assert(member->isClumpMember());
+						if (member->shape->getClassIndex() ==  Sph_Index){//clump member should be a sphere
+							const Sphere* sphere = YADE_CAST<Sphere*> (member->shape.get());
+							if ((gridPoint - member->state->pos).squaredNorm() <= pow(sphere->radius,2.)) { isInside = true; break; }
+						}
+					}
+					if (isInside) c_in += 1;
+				}
+			}
+		}
+		//return estimated volume:
+		Real vol_estimated = ((1.*c_in)/(1.*pow(numPoints1D,3.)))*abs(xmax-xmin)*abs(ymax-ymin)*abs(zmax-zmin);
+		if (vol_estimated <= 0.0) {PyErr_Warn(PyExc_UserWarning,("Something went wrong in getClumpVolume method (clump volume <= 0 detected for clump with id "+lexical_cast<string>(b->getId())+").").c_str()); return 0;}
+		else return vol_estimated;
+	}
+	python::list adaptClumpMasses(python::list excludeList, int num_tries){
+		python::list ret;
+		Scene* scene(Omega::instance().getScene().get());	// get scene
+		shared_ptr<Sphere> sph (new Sphere);
+		int Sph_Index = sph->getClassIndexStatic();		// get sphere index for checking if bodies are spheres
+		//convert excludeList to a c++ list
+		vector<Body::id_t> excludeListC;
+		for (int ii = 0; ii < python::len(excludeList); ii++) excludeListC.push_back(python::extract<Body::id_t>(excludeList[ii])());
+		Real volClump, estimatedMass, radTmp, volSum, memberMass, inertiaTmp;
+		FOREACH(const shared_ptr<Body>& b, *proxee){
+			if ( ( !(std::find(excludeListC.begin(), excludeListC.end(), b->getId()) != excludeListC.end()) ) && (b->isClump()) ){
+				volClump = getClumpVolume(b,num_tries);
+				const shared_ptr<Clump>& clump=YADE_PTR_CAST<Clump>(b->shape);
+				std::map<Body::id_t,Se3r>& members = clump->members;
+				volSum = 0.0;
+				estimatedMass = 0.0;
+				for (int ii = 0; ii < 2; ii++){
+					FOREACH(MemberMap::value_type& mm, members){
+						const Body::id_t& memberId=mm.first;
+						const shared_ptr<Body>& member=Body::byId(memberId,scene);
+						assert(member->isClumpMember());
+						radTmp = 0.0;
+						if (member->shape->getClassIndex() ==  Sph_Index){//clump member should be a sphere
+							const Sphere* sphere = YADE_CAST<Sphere*> (member->shape.get());
+							radTmp = sphere->radius;
+						}
+						if (ii == 0) volSum += (4./3.)*Mathr::PI*pow(radTmp,3.);
+						else {
+							shared_ptr<Material> matTmp = member->material;
+							memberMass = (volClump/volSum)*(4./3.)*Mathr::PI*pow(radTmp,3.)*matTmp->density;
+							member->state->mass = memberMass;//set vol. corrected mass for clump members
+							inertiaTmp = 2.0/5.0*memberMass*radTmp*radTmp;
+							member->state->inertia = Vector3r(inertiaTmp,inertiaTmp,inertiaTmp);
+							estimatedMass += memberMass;
+						}
+					}
+				}
+				Clump::updateProperties(b,/*intersecting*/ false);
+				ret.append(python::make_tuple(b->getId(),estimatedMass));
+			}
+		}
+		return ret;
+	}
+	Real getRoundness(python::list excludeList){
+		Scene* scene(Omega::instance().getScene().get());	// get scene
+		shared_ptr<Sphere> sph (new Sphere);
+		int Sph_Index = sph->getClassIndexStatic();		// get sphere index for checking if bodies are spheres
+		//convert excludeList to a c++ list
+		vector<Body::id_t> excludeListC;
+		for (int ii = 0; ii < python::len(excludeList); ii++) excludeListC.push_back(python::extract<Body::id_t>(excludeList[ii])());
+		Real RC_sum = 0.0;	//sum of local roundnesses
+		Real R1, R2, vol_tmp;
+		int c = 0;		//counter
+		FOREACH(const shared_ptr<Body>& b, *proxee){
+			if ( !(std::find(excludeListC.begin(), excludeListC.end(), b->getId()) != excludeListC.end()) ) {
+				if ((b->shape->getClassIndex() ==  Sph_Index) && (b->isStandalone())) { RC_sum += 1.0; c += 1; }
+				if (b->isClump()){
+					R2 = 0.0;
+					const shared_ptr<Clump>& clump=YADE_PTR_CAST<Clump>(b->shape);
+					std::map<Body::id_t,Se3r>& members = clump->members;
+					FOREACH(MemberMap::value_type& mm, members){
+						const Body::id_t& memberId=mm.first;
+						const shared_ptr<Body>& member=Body::byId(memberId,scene);
+						assert(member->isClumpMember());
+						if (member->shape->getClassIndex() ==  Sph_Index){//clump member should be a sphere
+							const Sphere* sphere = YADE_CAST<Sphere*> (member->shape.get());
+							R2 = max((member->state->pos - b->state->pos).norm() + sphere->radius, R2);	//get minimum radius of a sphere, that imbeds clump
+						}
+					}
+					vol_tmp = getClumpVolume(b,100000);//for RC an accuracy of +/- 1/100000 should be ok
+					R1 = pow((3.*vol_tmp)/(4.*Mathr::PI),1./3.);	//get theoretical radius of a sphere, with same volume as clump
+					if (R2 < R1) {PyErr_Warn(PyExc_UserWarning,("Something went wrong in getRoundness method (R2 < R1 detected).")); return 0;}
+					RC_sum += R1/R2; c += 1;
+				}
+			}
+		}
+		if (c == 0) c = 1;	//in case no spheres and no clumps are present in the scene: RC = 0
+		return RC_sum/c;	//return roundness coefficient RC
+	}
 	vector<Body::id_t> replace(vector<shared_ptr<Body> > bb){proxee->clear(); return appendList(bb);}
 	long length(){return proxee->size();}
 	void clear(){proxee->clear();}
@@ -400,7 +736,7 @@
 		return OMEGA.memSavedSimulations[":memory:"+mark];
 	}
 
-	void reset(){Py_BEGIN_ALLOW_THREADS; OMEGA.reset(); Py_END_ALLOW_THREADS; }
+	void reset(){OMEGA.stop(); OMEGA.reset(); }
 	void resetThisScene(){Py_BEGIN_ALLOW_THREADS; OMEGA.stop(); Py_END_ALLOW_THREADS; OMEGA.resetCurrentScene(); OMEGA.createSimulationLoop();}
 	void resetCurrentScene(){Py_BEGIN_ALLOW_THREADS; OMEGA.stop(); Py_END_ALLOW_THREADS; OMEGA.resetCurrentScene(); OMEGA.createSimulationLoop();}
 	void resetTime(){ OMEGA.getScene()->iter=0; OMEGA.getScene()->time=0; OMEGA.timeInit(); }
@@ -564,7 +900,7 @@
 		.def("addScene",&pyOmega::addScene,"Add new scene to Omega, returns its number")
 		.def("switchToScene",&pyOmega::switchToScene,"Switch to defined scene. Default scene has number 0, other scenes have to be created by addScene method.")
 		.def("switchScene",&pyOmega::switchScene,"Switch to alternative simulation (while keeping the old one). Calling the function again switches back to the first one. Note that most variables from the first simulation will still refer to the first simulation even after the switch\n(e.g. b=O.bodies[4]; O.switchScene(); [b still refers to the body in the first simulation here])")
-		.def("labeledEngine",&pyOmega::labeled_engine_get,"Return instance of engine/functor with the given label. This function shouldn't be called by the user directly; every ehange in O.engines will assign respective global python variables according to labels.\n\nFor example::\n\tO.engines=[InsertionSortCollider(label='collider')]\n\tcollider.nBins=5 ## collider has become a variable after assignment to O.engines automatically)")
+		.def("labeledEngine",&pyOmega::labeled_engine_get,"Return instance of engine/functor with the given label. This function shouldn't be called by the user directly; every ehange in O.engines will assign respective global python variables according to labels.\n\nFor example:\n\n\t *O.engines=[InsertionSortCollider(label='collider')]*\n\n\t *collider.nBins=5 # collider has become a variable after assignment to O.engines automatically*")
 		.def("resetTime",&pyOmega::resetTime,"Reset simulation time: step number, virtual and real time. (Doesn't touch anything else, including timings).")
 		.def("plugins",&pyOmega::plugins_get,"Return list of all plugins registered in the class factory.")
 		.def("_sceneObj",&pyOmega::scene_get,"Return the :yref:`scene <Scene>` object. Debugging only, all (or most) :yref:`Scene` functionality is proxies through :yref:`Omega`.")
@@ -602,8 +938,13 @@
 		.def("__iter__",&pyBodyContainer::pyIter)
 		.def("append",&pyBodyContainer::append,"Append one Body instance, return its id.")
 		.def("append",&pyBodyContainer::appendList,"Append list of Body instance, return list of ids")
-		.def("appendClumped",&pyBodyContainer::appendClump,"Append given list of bodies as a clump (rigid aggregate); return list of ids.")
-		.def("clump",&pyBodyContainer::clump,"Clump given bodies together (creating a rigid aggregate); returns clump id.")
+		.def("appendClumped",&pyBodyContainer::appendClump,"Append given list of bodies as a clump (rigid aggregate); returns a tuple of ``(clumpId,[memberId1,memberId2,...])``.")
+		.def("clump",&pyBodyContainer::clump,"Clump given bodies together (creating a rigid aggregate); returns ``clumpId``.")
+		.def("addToClump",&pyBodyContainer::addToClump,"Add body b to an existing clump c. c must be clump and b may not be a clump member of c.\n\nSee **/examples/clumps/addToClump-example.py** for an example script.\n\n.. note:: If b is a clump itself, then all members will be added to c and b will be deleted. If b is a clump member of clump d, then all members from d will be added to c and d will be deleted. If you need to add just clump member b, :yref:`release<BodyContainer.releaseFromClump>` this member from d first.")
+		.def("releaseFromClump",&pyBodyContainer::releaseFromClump,"Release body b from clump c. b must be a clump member of c.\n\nSee **/examples/clumps/releaseFromClump-example.py** for an example script.\n\n.. note:: If c contains only 2 members b will not be released and a warning will appear. In this case clump c should be :yref:`erased<BodyContainer.erase>`.")
+		.def("replaceByClumps",&pyBodyContainer::replaceByClumps,"Replace spheres by clumps using a list of clump templates and a list of amounts; returns a list of tuples: ``[(clumpId1,[memberId1,memberId2,...]),(clumpId2,[memberId1,memberId2,...]),...]``. A new clump will have the same volume as the sphere, that was replaced (clump volume/mass/inertia is accounting for overlaps assuming that there are only pair overlaps, to adapt masses of clumps with multiple overlaps use :yref:`adaptClumpMasses()<BodyContainer.adaptClumpMasses>`). \n\n\t *O.bodies.replaceByClumps( [utils.clumpTemplate([1,1],[.5,.5])] , [.9] ) #will replace 90 % of all standalone spheres by 'dyads'*\n\nSee **/examples/clumps/replaceByClumps-example.py** for an example script.")
+		.def("adaptClumpMasses",&pyBodyContainer::adaptClumpMasses,"Adapt clump masses and inertia via deterministic Monte-Carlo algorithm, that estimates clump volume using a regular grid of points; returns a list of tuples: ``[(clumpId1,estimatedMassOfClump1),(clumpId2,estimatedMassOfClump2),...]``.\n\nIt is recommended to use this method, when clumps where created via :yref:`clump()<BodyContainer.clump>` or :yref:`appendClumped()<BodyContainer.appendClumped>`. This method could also be used to adapt masses of clumps with multiple overlaps (e.g. triple sections). Bodies can be excluded from the calculation by giving a list of ids: *O.bodies.adaptClumpMasses([ids],1000000) #number of grid points is set to 1000000*\n\nSee **/examples/clumps/adaptClumpMasses-example.py** for an example script.")
+		.def("getRoundness",&pyBodyContainer::getRoundness,"Returns roundness coefficient RC = R2/R1. R1 is the theoretical radius of a sphere, with same volume as clump. R2 is the minimum radius of a sphere, that imbeds clump. If just spheres are present RC = 1. If clumps are present 0 < RC < 1. Bodies can be excluded from the calculation by giving a list of ids: *O.bodies.getRoundness([ids])*.\n\nSee **/examples/clumps/replaceByClumps-example.py** for an example script.")
 		.def("clear", &pyBodyContainer::clear,"Remove all bodies (interactions not checked)")
 		.def("erase", &pyBodyContainer::erase,"Erase body with the given id; all interaction will be deleted by InteractionLoop in the next step.")
 		.def("replace",&pyBodyContainer::replace);

=== modified file 'py/ymport.py'
--- py/ymport.py	2012-10-15 14:05:38 +0000
+++ py/ymport.py	2013-04-24 16:19:28 +0000
@@ -3,9 +3,13 @@
 """
 
 from yade.wrapper import *
-from miniEigen import *
 from yade import utils
 
+try:
+	from minieigen import *
+except ImportError:
+	from miniEigen import *
+
 def textExt(fileName,format='x_y_z_r',shift=Vector3.Zero,scale=1.0,**kw):
 	"""Load sphere coordinates from file in specific format, create spheres, insert them to the simulation.
 	
@@ -324,3 +328,33 @@
 		return unvReader.facets, unvReader.nodes, unvReader.elements
 	return facets
 
+
+def iges(fileName,shift=(0,0,0),scale=1.0,returnConnectivityTable=False,**kw):
+	""" Import triangular mesh from .igs file, return list of created facets.
+
+		:param string fileName: name of iges file
+		:param (float,float,float)|Vector3 shift: (X,Y,Z) parameter moves the specimen.
+		:param float scale: factor scales the given data.
+		:param \*\*kw: (unused keyword arguments) is passed to :yref:`yade.utils.facet`
+		:param bool returnConnectivityTable: if True, apart from facets returns also nodes (list of (x,y,z) nodes coordinates) and elements (list of (id1,id2,id3) element nodes ids). If False (default), returns only facets
+	
+	Example: :ysrc:`examples/test/unv-read/unvRead.py`."""
+	nodes,elems = [],[]
+	f = open(fileName)
+	for line in f:
+		if line.startswith('134'): # read nodes coordinates
+			ls = line.split(',')
+			v = Vector3(
+				float(ls[1])*scale + shift[0],
+				float(ls[2])*scale + shift[1],
+				float(ls[3])*scale + shift[2]
+			)
+			nodes.append(v)
+		if line.startswith('136'): # read elements
+			ls = line.split(',')
+			i1,i2,i3 = int(ls[3])/2, int(ls[4])/2, int(ls[5])/2 # the numbering of nodes is 1,3,5,7,..., hense this int(ls[*])/2
+			elems.append( (i1,i2,i3) )
+	facets = [utils.facet( ( nodes[e[0]], nodes[e[1]], nodes[e[2]] ), **kw) for e in elems]
+	if returnConnectivityTable:
+		return facets, nodes, elems
+	return facets

=== modified file 'scripts/README'
--- scripts/README	2007-03-31 06:18:17 +0000
+++ scripts/README	2013-03-18 20:56:36 +0000
@@ -1,42 +1,2 @@
 In this directory are placed scripts that help managing yade project.
 
-
-Due to many changes in yade directory structure and design many of those
-scripts no longer work, and need some modifications or can be deleted.
-I can't test everything now, but I don't want to delete them (even though
-they will be in subversion history). 
-So working scripts are in this directory, all other scripts are in
-directory 'untested'
-
-Olivier: if you test any of those scripts from 'untested', please move
-it back to yade-scripts. After some time we will delete obsolete
-scripts from 'untested'.
-
-                                                     / Janek /
-
-
-usually scripts should be invoked from different directory than
-trunk/yade-scripts
-
-
-TESTED SCRIPTS:
-
-setDebug , 
-setRelease        : invoke from trunk/
-                    switch between debug and release
-
-svndiff num1 num2 : prints svn diff between revisions num1 and num2. useful in
-                    connection with kompare:
-		      svndiff 800 820 > tmpfile ; kompare tmpfile
-
-makeFlat          : invoke from trunk/
-                    make symlinks of all source files (.cpp, .tpp, .h, .c, .ipp)
-		    in yade-flat.
-rmFlast	          : invoke from trunk/
-                    this script cleans after makeFlat script
-		    
-renameClassFirst        name1 name2
-renameClassFilenames    name1 name2
-renameClassDirectories  name1 name2    : invoke from trunk/
-                                         scripts that make it easier to change
-                                         globally class names (very useful).

=== removed directory 'scripts/debian'
=== removed file 'scripts/debian-packages'
--- scripts/debian-packages	2010-06-13 21:28:46 +0000
+++ scripts/debian-packages	1970-01-01 00:00:00 +0000
@@ -1,39 +0,0 @@
-#!/bin/sh
-# prepare sources for building debian packages
-# copy this script to a clean directory and run
-set -e -x
-
-RELEASE="0.50" # version we are preparing packages for
-UPDATE=.1 # empty or number such as .1, .2 (package yade-0.50, but verion 0.50.1)
-KEYID=62A21250  # key ID of the creator (password will be asked)
-DISTS="lucid" # distributions for which packages will be built and uploaded 
-BASE="/home/vaclav/yade/yade-0.50" # base branch to clean checkout from
-
-TOP=`pwd`
-[ -d yade-$RELEASE.bzr ] || bzr co --lightweight $BASE yade-$RELEASE.bzr
-rm -rf yade-$RELEASE; cp -r yade-$RELEASE.bzr yade-$RELEASE; rm -rf yade-$RELEASE/.bzr yade-$RELEASE/attic
-# temporarily disabled to used downloaded .orig.tar.gz from previous upload
-# tar -c yade-$RELEASE | gzip > yade-${RELEASE}_$RELEASE$UPDATE.orig.tar.gz
-cd yade-$RELEASE
-echo $RELEASE > RELEASE
-echo $UPDATE > UPDATE
-NPKGS=0 # track number of packages; the first one will have source included
-for DIST in $DISTS; do
-	scripts/debian-prep $DIST
-	# temporary fix for debian package version update
-	perl -pi -e 's/lucid1/lucid6/g' debian/changelog
-	if [ $NPKGS -eq 0 ]; then
-		UPLOAD=-sd # the first package is uploaded with upstream source
-	else
-		UPLOAD=-sd
-	fi
-	debuild -S $UPLOAD -k$KEYID -I;
-	NPKGS=$(( $NPKGS + 1 ))
-done
-
-cd $TOP
-
-for CHANGES in `ls -tr yade-${RELEASE}_$RELEASE$UPDATE-*_source.changes`; do
-	dput ppa:yade-users/ppa $CHANGES
-done
-

=== removed file 'scripts/debian-prep'
--- scripts/debian-prep	2011-02-17 19:47:20 +0000
+++ scripts/debian-prep	1970-01-01 00:00:00 +0000
@@ -1,80 +0,0 @@
-#!/usr/bin/python
-# encoding: utf-8
-import sys,os.path,re,shutil,time
-DISTRIBUTION=sys.argv[1] if len(sys.argv)>1 else 'unstable'
-
-
-if os.path.exists('RELEASE'):
-	VERSION=file('RELEASE').readline().strip()
-	UPDATE=(file('UPDATE').readline().strip() if os.path.exists('UPDATE') else '')
-	print 'UPDATE is %s'%UPDATE
-	SNAPSHOT=''
-	PRIORITY = 0
-	if ((re.sub('[^0-9.]','',VERSION))==''):
-		PRIORITY = 200
-	else:
-		PRIORITY=int(10000*float(re.sub('[^0-9.]','',VERSION)))
-		if re.match('^.*beta',VERSION): PRIORITY-=100
-		if re.match('^.*rc[0-9]$',VERSION): PRIORITY-=100
-		if UPDATE: PRIORITY+=int(re.sub('[^0-9]','',UPDATE))
-elif os.path.exists('.bzr'):
-	VERSION='bzr'+os.popen("LC_ALL=C bzr revno 2>/dev/null").readlines()[0][:-1]
-	SNAPSHOT='-snapshot'
-	PRIORITY=int(re.sub('[^0-9]','',VERSION))
-	UPDATE=''
-else:
-	raise RuntimeError('Revision could not be determined (RELEASE or .bzr)')
-print 'version %s%s%s, priority %d'%(VERSION,SNAPSHOT,('%s%s'%(VERSION,UPDATE) if UPDATE else ''),PRIORITY)
-open('VERSION','w').write(VERSION+'\n')
-_VERSION='-'+VERSION #used in templates
-
-
-# rename a current folder and create orig.tar.gz
-curName = os.path.basename(os.path.abspath(''))
-newName = 'yade-%s' % (VERSION)
-os.rename (('../'+curName), '../'+newName)
-shutil.rmtree('.bzr')
-os.system(('tar -czf ../yade-%s_%s.orig.tar.gz ../'+os.path.basename(os.path.abspath(''))+'/')%(VERSION,VERSION))
-shutil.copytree('scripts/debian','./debian')
-
-
-# control files
-def copyReplace(f1,f2):
-	"Copy file f1 to f2, evaluating all occurences of @...@ with eval(); they should expand to a string and can contain arbitrary python expressions."
-	ff2=open(f2,'w')
-	for l in open(f1):
-		ff2.write(re.sub(r'@([^@]*)@',lambda m: str(eval(m.group(1))),l))
-for f1,f2 in [
-	('yade.postinst-template','yade-%s.postinst'%VERSION),
-	('yade.desktop-template','yade-%s.desktop'%VERSION),
-	('yade.docs-template','yade-%s.docs'%VERSION),
-	('yade.examples-template','yade-%s.examples'%VERSION),
-	('yade.install-template','yade-%s.install'%VERSION),
-	('yade.menu-template','yade-%s.menu'%VERSION),
-	('yade-doc.doc-base-template','yade-%s-doc.doc-base'%VERSION),
-	('yade-doc.docs-template','yade-%s-doc.docs'%VERSION),
-	('control-template','control')]:
-		copyReplace('debian/'+f1,'debian/'+f2)
-os.system('cp debian/yade16x16.xpm debian/yade-%s_16x16.xpm'%VERSION)
-os.system('cp debian/yade32x32.xpm debian/yade-%s_32x32.xpm'%VERSION)
-
-
-# package is yade-0.50, but with UPDATE .1, it is version 0.50.1
-
-# write debian/changelog
-try:
-	open('debian/changelog','w').write(
-	'''yade-%s (%s-1) %s; urgency=low
-
-  * Automatic debian changelog entry for yade-%s
-
- -- %s <%s>  %s
-'''%(VERSION,VERSION,DISTRIBUTION,VERSION,os.environ['DEBFULLNAME'],os.environ['DEBEMAIL'],time.strftime("%a, %d %b %Y %H:%M:%S +0000",time.gmtime())))
-except KeyError:
-	print "Please, set DEBEMAIL and DEBFULLNAME as described here http://www.debian.org/doc/maint-guide/ch-first.en.html";
-
-# remove some generated files
-for p in ('doc/doxygen','doc/sphinx/_build','tags'):
-	if not os.path.exists(p): continue
-	if os.path.isdir(p): shutil.rmtree(p)
-	else: os.remove(p)

=== removed file 'scripts/debian/compat'
--- scripts/debian/compat	2011-02-08 07:37:09 +0000
+++ scripts/debian/compat	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-5

=== removed file 'scripts/debian/control-template'
--- scripts/debian/control-template	2011-02-21 14:45:36 +0000
+++ scripts/debian/control-template	1970-01-01 00:00:00 +0000
@@ -1,107 +0,0 @@
-Source: yade@_VERSION@
-Section: x11
-Priority: optional
-Homepage: https://launchpad.net/yade
-Maintainer: Anton Gladky <gladky.anton@xxxxxxxxx>
-Build-Depends: debhelper (>= 5), scons, freeglut3-dev, libboost-dev (>=1.35), libboost-date-time-dev (>=1.35), libboost-filesystem-dev (>=1.35), libboost-thread-dev (>=1.35), libboost-regex-dev (>=1.35), libboost-python-dev (>=1.35), libboost-iostreams-dev (>=1.35), libboost-program-options-dev, python-support, libboost-serialization-dev, libloki-dev, liblog4cxx9-dev | liblog4cxx10-dev, docbook-to-man, ipython, libgts-dev, python-numpy, g++(>>4.0), libvtk5-dev, libgl1-mesa-dev, gdb, python-matplotlib, python-tk, libeigen2-dev, libqglviewer-qt4-dev , binutils-gold , texlive-latex-recommended, texlive-latex-extra, lmodern, texlive-pictures, texlive-xetex, python-sphinx (>=1.0.6), python-bibtex, graphviz, dvipng, python-xlib, python-qt4, pyqt4-dev-tools, clang, libjs-jquery, python-imaging
-Standards-Version: 3.9.1
-
-Package: yade@_VERSION@
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, ${python:Depends}, python-numpy, ipython, python-matplotlib, python-tk, python-qt4, python-xlib, mencoder, gnuplot, python-imaging, libjs-jquery
-Description: Platform for discrete element modeling. Main optimized build
- Yet Another Dynamic Engine.
- .
- Extensible open-source framework for discrete numerical models, 
- focused on Discrete Element Method. 
- The computation parts are written in c++ using flexible object model, 
- allowing independent implementation of new algorithms and interfaces. 
- Python is used for rapid and concise scene construction, 
- simulation control, postprocessing and debugging.
- .
- This package contains speed-optimized build of yade.
-
-Package: yade@_VERSION@-dbg
-Architecture: any
-Section: debug
-Priority: extra
-Depends: ${shlibs:Depends}, ${misc:Depends}, yade@_VERSION@, gdb
-Description: Platform for discrete element modeling. Debug build
- Yet Another Dynamic Engine.
- .
- Extensible open-source framework for discrete numerical models, 
- focused on Discrete Element Method. 
- The computation parts are written in c++ using flexible object model, 
- allowing independent implementation of new algorithms and interfaces. 
- Python is used for rapid and concise scene construction, 
- simulation control, postprocessing and debugging.
- .
- This package contains debug build of yade.
-
-Package: yade@_VERSION@-doc
-Architecture: all
-Section: doc
-Recommends: yade@_VERSION@ | yade@_VERSION@-dbg
-Depends: ${misc:Depends}
-Description: Platform for discrete element modeling. Documentation
- Yet Another Dynamic Engine.
- .
- Extensible open-source framework for discrete numerical models, 
- focused on Discrete Element Method. 
- The computation parts are written in c++ using flexible object model, 
- allowing independent implementation of new algorithms and interfaces. 
- Python is used for rapid and concise scene construction, 
- simulation control, postprocessing and debugging.
- .
- This package contains examples, test scripts and documentation.
-
-Package: yade
-Architecture: all
-Depends: yade@_VERSION@, ${misc:Depends}
-Description: Platform for discrete element modeling. Snapshot version
- Yet Another Dynamic Engine.
- .
- Extensible open-source framework for discrete numerical models, 
- focused on Discrete Element Method. 
- The computation parts are written in c++ using flexible object model, 
- allowing independent implementation of new algorithms and interfaces. 
- Python is used for rapid and concise scene construction, 
- simulation control, postprocessing and debugging.
- .
- This package depends on the latest
- stable release of Yade, virtual package.
-
-Package: yade-dbg
-Architecture: all
-Section: debug
-Priority: extra
-Depends: yade@_VERSION@-dbg, yade@_VERSION@, ${misc:Depends}
-Description: Platform for discrete element modeling. Snapshot debug version
- Yet Another Dynamic Engine.
- .
- Extensible open-source framework for discrete numerical models, 
- focused on Discrete Element Method. 
- The computation parts are written in c++ using flexible object model, 
- allowing independent implementation of new algorithms and interfaces. 
- Python is used for rapid and concise scene construction, 
- simulation control, postprocessing and debugging.
- .
- This package depends on the latest debug build of
- stable release of Yade, virtual package
-
-Package: yade-doc
-Architecture: all
-Section: doc
-Depends: yade@_VERSION@-doc, ${misc:Depends}
-Description: Platform for discrete element modeling. Snapshot documentation
- Yet Another Dynamic Engine.
- .
- Extensible open-source framework for discrete numerical models, 
- focused on Discrete Element Method. 
- The computation parts are written in c++ using flexible object model, 
- allowing independent implementation of new algorithms and interfaces. 
- Python is used for rapid and concise scene construction, 
- simulation control, postprocessing and debugging.
- .
- This package depends on the latest documentation of
- stable release of Yade, virtual package.

=== removed file 'scripts/debian/copyright'
--- scripts/debian/copyright	2011-02-08 07:37:09 +0000
+++ scripts/debian/copyright	1970-01-01 00:00:00 +0000
@@ -1,224 +0,0 @@
-Format: http://dep.debian.net/deps/dep5/
-Source: https://launchpad.net/yade
-
-Files: *
-Copyright: 2004-2011 Yade developers <yade-dev@xxxxxxxxxxxxxxxxxxx>
-           Václav Šmilauer <eudoxos@xxxxxxxx>
-           Olivier Galizzi <olivier.galizzi@xxxxxxx>
-           Janek Kozicki <janek@xxxxxxxxxx>
-           Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>
-           Anton Gladky <gladky.anton@xxxxxxxxx>
-           Sergei Dorofeenko <dorofeenko@xxxxxxxxx>
-           Jerome Duriez <duriez@xxxxxxxxxxxxxxx>
-           Vincent Richefeu <richefeu@xxxxxxxxx>
-           Chiara Modenese <c.modenese@xxxxxxxxx>
-           Boon Chiaweng <booncw@xxxxxxxxxxx>
-           Emanuele Catalano <catalano@xxxxxxxxxxx>
-           Luc Scholtes <lscholtes63@xxxxxxxxx>
-           Jan Stránský <_honzik@xxxxxxxxxx>
-           Luc Sibille <luc.sibille@xxxxxxxxxxxxxx>
-           Feng Chen <fchen3@xxxxxxx>
-License: GPL-2
- This program is free software; you can redistribute it
- and/or modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2 of the License.
- .
- This program is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE.  See the GNU General Public License for more
- details.
- .
- You should have received a copy of the GNU General Public
- License along with this package; if not, write to the Free
- Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- Boston, MA  02110-1301 USA
- .
- On Debian systems, the full text of the GNU General Public
- License version 2 can be found in the file
- `/usr/share/common-licenses/GPL-2'.
-
-Files: extra/floating_point_utilities_v3/boost/*
-Copyright: 2006 Johan Rade
-License: Boost Software License, Version 1.0
- Boost Software License - Version 1.0 - August 17th, 2003
- .
- Permission is hereby granted, free of charge, to any person or organization
- obtaining a copy of the software and accompanying documentation covered by
- this license (the "Software") to use, reproduce, display, distribute,
- execute, and transmit the Software, and to prepare derivative works of the
- Software, and to permit third-parties to whom the Software is furnished to
- do so, all subject to the following:
- .
- The copyright notices in the Software and this entire statement, including
- the above license grant, this restriction and the following disclaimer,
- must be included in all copies of the Software, in whole or in part, and
- all derivative works of the Software, unless such copies or derivative
- works are solely in the form of machine-executable object code generated by
- a source language processor.
- .
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
- SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
- FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
- ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
- http://www.boost.org/LICENSE_1_0.txt
-
-Files: extra/boost_python_len.hpp
-Copyright: 2002 David Abrahams
-License: Boost Software License, Version 1.0
- Boost Software License - Version 1.0 - August 17th, 2003
- .
- The full text see above.
- http://www.boost.org/LICENSE_1_0.txt
-
-Files: extra/foreach.hpp_local
-Copyright: 2004 Eric Niebler
-License: Boost Software License, Version 1.0
- Boost Software License - Version 1.0 - August 17th, 2003
- .
- The full text see above.
- http://www.boost.org/LICENSE_1_0.txt
-
-Files: py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/algorithms.hpp
-Copyright: 2003 Raoul M. Gough
-License: Boost Software License, Version 1.0
- Boost Software License - Version 1.0 - August 17th, 2003
- .
- The full text see above.
- http://www.boost.org/LICENSE_1_0.txt
-
-Files: py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/*
-Copyright: 2003-2004 Raoul M. Gough
-License: Boost Software License, Version 1.0
- Boost Software License - Version 1.0 - August 17th, 2003
- .
- The full text see above.
- http://www.boost.org/LICENSE_1_0.txt
-
-Files: py/3rd-party/boost-python-indexing-suite-v2-noSymlinkHeaders/pair.hpp
-Copyright: 2007 Roman Yakovenko
-License: Boost Software License, Version 1.0
- Boost Software License - Version 1.0 - August 17th, 2003	
- .
- The full text see above.
- http://www.boost.org/LICENSE_1_0.txt
-
-Files: py/3rd-party/mtTkinter-0.3/*
-Copyright: Allen B. Taylor <a.b.taylor@xxxxxxxxx>
-License: Unspecified
- Released under LGPL from version 0.4
-
-Files: py/3rd-party/pygts-0.3.1/*
-Copyright: 1999 Stéphane Popinet
-           2009 Thomas J. Duck
-License: GPL-2+
- This program is free software; you can redistribute it
- and/or modify it under the terms of the GNU General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later
- version.
- .
- This program is distributed in the hope that it will be
- useful, but WITHOUT ANY WARRANTY; without even the implied
- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE.  See the GNU General Public License for more
- details.
- .
- You should have received a copy of the GNU General Public
- License along with this package; if not, write to the Free
- Software Foundation, Inc., 51 Franklin St, Fifth Floor,
- Boston, MA  02110-1301 USA
- .
- On Debian systems, the full text of the GNU General Public
- License version 2 can be found in the file
- `/usr/share/common-licenses/GPL-2'.
-
-Files: lib/pyutil/numpy_boost.hpp
-Copyright: 2008 Michael Droettboom
-License: BSD
- Copyright (c) The Regents of the University of California.
- All rights reserved.
- .
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
-    notice, this list of conditions and the following disclaimer in the
-    documentation and/or other materials provided with the distribution.
- 3. Neither the name of the University nor the names of its contributors
-    may be used to endorse or promote products derived from this software
-    without specific prior written permission.
- .
- THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- SUCH DAMAGE.
-
-Files: site_scons/site_tools/qt4/__init__.py
-Copyright: 2001-7,2010 The SCons Foundation
-License: MIT/X11 (BSD like)
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
- .
- The above copyright notice and this permission notice shall be included
- in all copies or substantial portions of the Software.
- .
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
- KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Files: scripts/test/HTML.py
-Copyright: 2009 Philippe Lagadec
-License: CeCILL (open-source GPL compatible)
- The purpose of this Free Software license agreement is to grant users
- the right to modify and redistribute the software governed by this
- license within the framework of an open source distribution model.
- .
- The exercising of these rights is conditional upon certain obligations
- for users so as to preserve this status for all subsequent redistributions.
- .
- In consideration of access to the source code and the rights to copy,
- modify and redistribute granted by the license, users are provided only
- with a limited warranty and the software's author, the holder of the
- economic rights, and the successive licensors only have limited liability.
- .
- In this respect, the risks associated with loading, using, modifying
- and/or developing or reproducing the software by the user are brought to
- the user's attention, given its Free Software status, which may make it
- complicated to use, with the result that its use is reserved for
- developers and experienced professionals having in-depth computer
- knowledge. Users are therefore encouraged to load and test the
- suitability of the software as regards their requirements in conditions
- enabling the security of their systems and/or data to be ensured and,
- more generally, to use and operate it in the same conditions of
- security. This Agreement may be freely reproduced and published,
- provided it is not altered, and that no provisions are either added or
- removed herefrom.
- .
- This Agreement may apply to any or all software for which the holder of
- the economic rights decides to submit the use thereof to its provisions.
- .
- The full text of the License can be obtained on the web-page
- http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt

=== removed file 'scripts/debian/rules'
--- scripts/debian/rules	2011-02-08 07:37:09 +0000
+++ scripts/debian/rules	1970-01-01 00:00:00 +0000
@@ -1,76 +0,0 @@
-#!/usr/bin/make -f
-
-export VERSION=$(shell cat VERSION)
-export _VERSION=-${VERSION}
-
-configure: configure-stamp
-configure-stamp:
-	dh_testdir
-	touch configure-stamp
-build: build-stamp
-
-build-stamp: configure-stamp 
-	dh_testdir
-	touch $@
-
-clean:
-	dh_testdir
-	dh_testroot
-	rm -f build-stamp configure-stamp
-	## eudoxos: FIXME: scons skips config when cleaning and doesn't know where it built anything
-	dh_testdir
-	# scons clean
-	## remove builddirs and installation directories
-	rm -rf debian/build-* `find debian/ -name 'yade-*' -type d`
-	rm -rf doc/sphinx/_build
-	rm -rf tags
-	dh_clean 
-
-install: build
-	dh_testdir
-	dh_testroot
-	dh_installdirs
-	## files VERSION and _VERSION contain snapshot version without/with leading '-' respectively (like svn1113 and -svn1113)
-	#debug build
-	# remove the profile, if existing, to have clean config
-	rm -f scons.profile-deb
-	# the last argument specified that we only want files in lib installed -- common files (the executable) are already in the optimized package
-	NO_SCONS_GET_RECENT= scons profile=deb buildPrefix=debian runtimePREFIX=/usr version=${VERSION} brief=0 chunkSize=5 jobs=1 features=openmp,vtk,gts,opengl,qt4 PREFIX=debian/yade${_VERSION}-dbg/usr variant='' optimize=0 march= debug=1 debian/yade${_VERSION}-dbg/usr/lib
-	#optimized build
-	NO_SCONS_GET_RECENT= scons profile=deb PREFIX=debian/yade${_VERSION}/usr variant='' optimize=1 debug=0
-	cd doc/sphinx; PYTHONPATH=. YADE_PREFIX=../../debian/yade${_VERSION}/usr/ ../../debian/yade${_VERSION}/usr/bin/yade${_VERSION} yadeSphinx.py; cd _build/latex; xelatex Yade.tex; xelatex Yade.tex; xelatex Yade.tex; cd ../..;
-	# generate manpages
-	YADE_PREFIX=debian/yade${_VERSION}/usr debian/yade${_VERSION}/usr/bin/yade${_VERSION} --generate-manpage yade${_VERSION}.1
-	YADE_PREFIX=debian/yade${_VERSION}/usr debian/yade${_VERSION}/usr/bin/yade${_VERSION}-batch --generate-manpage yade${_VERSION}-batch.1
-
-check: install
-	dh_testdir
-	dh_testroot
-	YADE_PREFIX=debian/yade${_VERSION}/usr debian/yade${_VERSION}/usr/bin/yade${_VERSION} --test
-	YADE_PREFIX=debian/yade${_VERSION}-dbg/usr debian/yade${_VERSION}/usr/bin/yade${_VERSION} --debug --test
-
-binary-indep: build install 
-
-binary-arch: build install check
-	dh_testdir
-	dh_testroot
-	dh_installchangelogs ChangeLog
-	dh_pysupport
-	dh_installdocs
-	dh_install
-	dh_installexamples
-	dh_installmenu
-	dh_installman -p yade${_VERSION} yade${_VERSION}.1 yade${_VERSION}-batch.1
-	dh_link
-	dh_strip --exclude=yade${_VERSION}-dbg   # don't strip the debug package
-	dh_compress --all -X.py -X.stl -X.gts -X.geo -X.mesh -X.msh -X.pdf -X.png -X.svg -X.txt -X.js -X.inv
-	dh_fixperms
-	dh_makeshlibs
-	dh_installdeb
-	dh_shlibdeps
-	dh_gencontrol
-	dh_md5sums
-	dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install configure

=== removed directory 'scripts/debian/source'
=== removed file 'scripts/debian/source/format'
--- scripts/debian/source/format	2011-02-08 07:37:09 +0000
+++ scripts/debian/source/format	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-3.0 (quilt)

=== removed file 'scripts/debian/watch'
--- scripts/debian/watch	2011-02-08 07:37:09 +0000
+++ scripts/debian/watch	1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
-version=3
-http://launchpad.net/yade/+download http://launchpad.net/yade/trunk/.*/yade-(.+).tar.bz2
-

=== removed file 'scripts/debian/yade-doc.doc-base-template'
--- scripts/debian/yade-doc.doc-base-template	2011-02-21 14:45:36 +0000
+++ scripts/debian/yade-doc.doc-base-template	1970-01-01 00:00:00 +0000
@@ -1,12 +0,0 @@
-Document: yade@_VERSION@-documentation
-Title: This documentation decribes Yade version @VERSION@
-Author: Yade developers <yade-dev@xxxxxxxxxxxxxxxxxxx>
-Abstract: Yade is an extensible open-source framework for discrete numerical models, focused on Discrete Element Method. The computation parts are written in c++ using flexible object model, allowing independent implementation of new alogrithms and interfaces. Python is used for rapid and concise scene construction, simulation control, postprocessing and debugging.
-Section: Science/Physics
-
-Format: html
-Index: /usr/share/doc/yade@_VERSION@-doc/html/index.html
-Files: /usr/share/doc/yade@_VERSION@-doc/*.*
-
-Format: PDF
-Files: /usr/share/doc/yade@_VERSION@-doc/Yade.pdf

=== removed file 'scripts/debian/yade-doc.docs-template'
--- scripts/debian/yade-doc.docs-template	2011-02-08 07:37:09 +0000
+++ scripts/debian/yade-doc.docs-template	1970-01-01 00:00:00 +0000
@@ -1,2 +0,0 @@
-doc/sphinx/_build/html
-doc/sphinx/_build/latex/Yade.pdf

=== removed file 'scripts/debian/yade.desktop-template'
--- scripts/debian/yade.desktop-template	2011-02-08 07:37:09 +0000
+++ scripts/debian/yade.desktop-template	1970-01-01 00:00:00 +0000
@@ -1,8 +0,0 @@
-[Desktop Entry]
-Type=Application
-Name=Yade @VERSION@
-GenericName=Yade
-Exec=/usr/bin/yade@_VERSION@
-Icon=/usr/share/pixmaps/yade@_VERSION@_32x32.xpm
-Terminal=true
-Categories=Education;Physics;Science;

=== removed file 'scripts/debian/yade.docs-template'
--- scripts/debian/yade.docs-template	2011-02-08 07:37:09 +0000
+++ scripts/debian/yade.docs-template	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-scripts

=== removed file 'scripts/debian/yade.examples-template'
--- scripts/debian/yade.examples-template	2011-02-08 07:37:09 +0000
+++ scripts/debian/yade.examples-template	1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
-examples/*

=== removed file 'scripts/debian/yade.install-template'
--- scripts/debian/yade.install-template	2011-02-08 07:37:09 +0000
+++ scripts/debian/yade.install-template	1970-01-01 00:00:00 +0000
@@ -1,3 +0,0 @@
-debian/yade@_VERSION@_16x16.xpm usr/share/pixmaps/
-debian/yade@_VERSION@_32x32.xpm usr/share/pixmaps/
-debian/yade@_VERSION@.desktop usr/share/applications/

=== removed file 'scripts/debian/yade.menu-template'
--- scripts/debian/yade.menu-template	2011-02-08 07:37:09 +0000
+++ scripts/debian/yade.menu-template	1970-01-01 00:00:00 +0000
@@ -1,8 +0,0 @@
-?package(yade@_VERSION@):\
-	needs="X11"\
-	section="Applications/Science/Physics"\
-	title="Yade (@VERSION@)"\
-	command="/usr/bin/yade@_VERSION@"\
-	icon="/usr/share/pixmaps/yade@_VERSION@_32x32.xpm"\
-	icon16x16="/usr/share/pixmaps/yade@_VERSION@_16x16.xpm"\
-	icon32x32="/usr/share/pixmaps/yade@_VERSION@_32x32.xpm"

=== removed file 'scripts/debian/yade.postinst-template'
--- scripts/debian/yade.postinst-template	2011-02-08 07:37:09 +0000
+++ scripts/debian/yade.postinst-template	1970-01-01 00:00:00 +0000
@@ -1,42 +0,0 @@
-#!/bin/sh
-# postinst script for yade
-#
-# see: dh_installdeb(1)
-
-set -e
-
-# summary of how this script can be called:
-#        * <postinst> `configure' <most-recently-configured-version>
-#        * <old-postinst> `abort-upgrade' <new version>
-#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
-#          <new-version>
-#        * <postinst> `abort-remove'
-#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
-#          <failed-install-package> <version> `removing'
-#          <conflicting-package> <version>
-# for details, see http://www.debian.org/doc/debian-policy/ or
-# the debian-policy package
-
-
-case "$1" in
-    configure)
-	 	update-alternatives --install /usr/bin/yade yade /usr/bin/yade@_VERSION@ @PRIORITY@ --slave /usr/bin/yade-batch yade-batch /usr/bin/yade@_VERSION@-batch --slave /usr/share/man/man1/yade.1 yade.1 /usr/share/man/man1/yade@_VERSION@.1 --slave /usr/share/man/man1/yade-batch.1 yade-batch.1 /usr/share/man/man1/yade@_VERSION@-batch.1
-    ;;
-
-    abort-upgrade|abort-remove|abort-deconfigure)
-    ;;
-
-    *)
-        echo "postinst called with unknown argument \`$1'" >&2
-        exit 1
-    ;;
-esac
-
-# dh_installdeb will replace this with shell code automatically
-# generated by other debhelper scripts.
-
-#DEBHELPER#
-
-exit 0
-
-

=== removed file 'scripts/debian/yade16x16.xpm'
--- scripts/debian/yade16x16.xpm	2011-02-08 07:37:09 +0000
+++ scripts/debian/yade16x16.xpm	1970-01-01 00:00:00 +0000
@@ -1,274 +0,0 @@
-/* XPM */
-static char * yade16x16_xpm[] = {
-"16 16 255 2",
-"  	c None",
-". 	c #E2A4A4",
-"+ 	c #8F9090",
-"@ 	c #A7AAAA",
-"# 	c #BDBEBE",
-"$ 	c #C5C6C5",
-"% 	c #AFAEAF",
-"& 	c #B7B8B7",
-"* 	c #BFBFBF",
-"= 	c #D2D1D2",
-"- 	c #C1C1C1",
-"; 	c #D3D4D3",
-"> 	c #D7D8D7",
-", 	c #C7C7C7",
-"' 	c #D7D7D7",
-") 	c #E6E6E6",
-"! 	c #DEDEDE",
-"~ 	c #FD6969",
-"{ 	c #F6C2C2",
-"] 	c #E28B8B",
-"^ 	c #DAC1C1",
-"/ 	c #C1C2C2",
-"( 	c #C4C4C4",
-"_ 	c #B3B3B3",
-": 	c #C5C5C5",
-"< 	c #CECECE",
-"[ 	c #BEBFBE",
-"} 	c #DBDBDB",
-"| 	c #D1D0D1",
-"1 	c #D0D0D0",
-"2 	c #F1F1F1",
-"3 	c #E0E0E0",
-"4 	c #FE6262",
-"5 	c #FFB8B9",
-"6 	c #E34445",
-"7 	c #7E523C",
-"8 	c #696B46",
-"9 	c #75753F",
-"0 	c #99999F",
-"a 	c #AEADAE",
-"b 	c #ADAEAD",
-"c 	c #CECFCE",
-"d 	c #B4B4B7",
-"e 	c #757455",
-"f 	c #7E7F52",
-"g 	c #737354",
-"h 	c #A6A7A8",
-"i 	c #FFFFFF",
-"j 	c #FB5050",
-"k 	c #FE9595",
-"l 	c #FEB8B8",
-"m 	c #635332",
-"n 	c #C2C301",
-"o 	c #BCBD02",
-"p 	c #49491D",
-"q 	c #B8B8B8",
-"r 	c #BEBEBE",
-"s 	c #CCCCCC",
-"t 	c #636338",
-"u 	c #DEDD05",
-"v 	c #F2F208",
-"w 	c #6D6D2A",
-"x 	c #D6D6D8",
-"y 	c #C7C7C9",
-"z 	c #EE6565",
-"A 	c #FCABAB",
-"B 	c #E5AEAE",
-"C 	c #D17A7C",
-"D 	c #C8A75E",
-"E 	c #BCB200",
-"F 	c #B1B405",
-"G 	c #4A4A47",
-"H 	c #B5B3B5",
-"I 	c #7F7E89",
-"J 	c #B2B100",
-"K 	c #BFBF01",
-"L 	c #868600",
-"M 	c #9999A1",
-"N 	c #C9C8CB",
-"O 	c #EAE9EB",
-"P 	c #FB4746",
-"Q 	c #FE9B9B",
-"R 	c #EE6D6D",
-"S 	c #FF5A59",
-"T 	c #FFADB5",
-"U 	c #DEA304",
-"V 	c #BBA900",
-"W 	c #787800",
-"X 	c #76757C",
-"Y 	c #66660C",
-"Z 	c #CDCC05",
-"` 	c #C9CA05",
-" .	c #535351",
-"..	c #ACACAF",
-"+.	c #BBBBBF",
-"@.	c #DCDCDF",
-"#.	c #F87575",
-"$.	c #FD4C4C",
-"%.	c #FEBDBC",
-"&.	c #FD6A6A",
-"*.	c #FD4F4E",
-"=.	c #FFA3AB",
-"-.	c #EFC490",
-";.	c #D0D001",
-">.	c #464608",
-",.	c #B1B201",
-"'.	c #B6B704",
-").	c #59581E",
-"!.	c #BEBDC1",
-"~.	c #C8C7CB",
-"{.	c #BCBBC2",
-"].	c #BFBEC5",
-"^.	c #FD999A",
-"/.	c #FA7878",
-"(.	c #FE4343",
-"_.	c #FD5E5E",
-":.	c #FE4747",
-"<.	c #FD8B8B",
-"[.	c #FF9293",
-"}.	c #CAB500",
-"|.	c #D3D307",
-"1.	c #B0B104",
-"2.	c #858603",
-"3.	c #7A7984",
-"4.	c #C3C2C7",
-"5.	c #E9E8EB",
-"6.	c #C2C0C9",
-"7.	c #C8C7CF",
-"8.	c #FD3939",
-"9.	c #E65A5A",
-"0.	c #F48585",
-"a.	c #FEBDBD",
-"b.	c #FE5A5A",
-"c.	c #FC3535",
-"d.	c #B84448",
-"e.	c #9F9800",
-"f.	c #A0A804",
-"g.	c #AAAC07",
-"h.	c #3A3A35",
-"i.	c #B1AEB6",
-"j.	c #9F9EA8",
-"k.	c #C8C5CE",
-"l.	c #D8D7DD",
-"m.	c #C8C6D0",
-"n.	c #FB4D4D",
-"o.	c #FB5C5C",
-"p.	c #FE6969",
-"q.	c #FDB3B3",
-"r.	c #F18E8E",
-"s.	c #F75656",
-"t.	c #FFAAAB",
-"u.	c #8C6D05",
-"v.	c #F29503",
-"w.	c #AB9500",
-"x.	c #8C8B98",
-"y.	c #9C9AA4",
-"z.	c #A6A6B0",
-"A.	c #A3A2AF",
-"B.	c #BAB9C4",
-"C.	c #A6A5B4",
-"D.	c #F90807",
-"E.	c #F91516",
-"F.	c #FB7373",
-"G.	c #FE4C4C",
-"H.	c #EE7272",
-"I.	c #EF7070",
-"J.	c #FF3B3D",
-"K.	c #744B01",
-"L.	c #F46907",
-"M.	c #AB5E05",
-"N.	c #A0A4B2",
-"O.	c #9895A3",
-"P.	c #9B98A7",
-"Q.	c #9695A6",
-"R.	c #A3A1B1",
-"S.	c #737388",
-"T.	c #DF3939",
-"U.	c #F21F1E",
-"V.	c #FB1818",
-"W.	c #F54A4A",
-"X.	c #FD9C9C",
-"Y.	c #FDD0D0",
-"Z.	c #FC7276",
-"`.	c #E1A586",
-" +	c #F29A06",
-".+	c #9B5F00",
-"++	c #B08D9A",
-"@+	c #8B8C9E",
-"#+	c #A39BAC",
-"$+	c #AAA7B9",
-"%+	c #A9A5B9",
-"&+	c #AAA7BB",
-"*+	c #E04746",
-"=+	c #EF0505",
-"-+	c #FC6161",
-";+	c #FC5D5D",
-">+	c #FC5658",
-",+	c #FA4C50",
-"'+	c #FA9094",
-")+	c #FCCDD2",
-"!+	c #E98D3C",
-"~+	c #A24C03",
-"{+	c #DEA8B1",
-"]+	c #EB6473",
-"^+	c #FAC1C7",
-"/+	c #B29FB0",
-"(+	c #A7A4B8",
-"_+	c #9A97B0",
-":+	c #E06060",
-"<+	c #F21615",
-"[+	c #FC2222",
-"}+	c #F83839",
-"|+	c #F04449",
-"1+	c #F85056",
-"2+	c #F53943",
-"3+	c #F85E6A",
-"4+	c #633D0D",
-"5+	c #4D2300",
-"6+	c #D33F51",
-"7+	c #EB7180",
-"8+	c #F9CACF",
-"9+	c #BA90A4",
-"0+	c #A7A5BC",
-"a+	c #F00808",
-"b+	c #F74142",
-"c+	c #F51A1B",
-"d+	c #F85252",
-"e+	c #E44D52",
-"f+	c #FC8F95",
-"g+	c #EA4D58",
-"h+	c #E04E5C",
-"i+	c #FF7B89",
-"j+	c #FFE1E7",
-"k+	c #EF7080",
-"l+	c #F07D8C",
-"m+	c #F5AAB6",
-"n+	c #C7758B",
-"o+	c #D7A3B5",
-"p+	c #A69EB6",
-"q+	c #FE0000",
-"r+	c #FF5656",
-"s+	c #FD1717",
-"t+	c #FB5F5F",
-"u+	c #F56565",
-"v+	c #CE2734",
-"w+	c #DE6874",
-"x+	c #E05D6C",
-"y+	c #EF4D5E",
-"z+	c #F17988",
-"A+	c #EC6678",
-"B+	c #E52D48",
-"C+	c #DD435E",
-"D+	c #D4627D",
-"E+	c #E96D84",
-"F+	c #A37E9D",
-". + @ # $ % & * = - ; > , ' ) ! ",
-"~ { ] ^ / ( _ : < [ = } | 1 2 3 ",
-"4 5 6 7 8 9 0 a b c d e f g h i ",
-"j k l m n o p q r s t u v w x y ",
-"z A B C D E F G H I J K L M N O ",
-"P Q R S T U V W X Y Z `  ...+.@.",
-"#.$.%.&.*.=.-.;.>.,.'.).!.~.{.].",
-"^./.(._.:.<.[.}.|.1.2.3.4.5.6.7.",
-"8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.m.",
-"n.o.p.q.r.s.t.u.v.w.x.y.z.A.B.C.",
-"D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.",
-"T.U.V.W.X.Y.Z.`. +.+++@+#+$+%+&+",
-"*+=+-+;+>+,+'+)+!+~+{+]+^+/+(+_+",
-":+<+[+}+|+1+2+3+4+5+6+7+8+9+  0+",
-"a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+",
-"q+r+s+t+u+v+w+x+y+z+A+B+C+D+E+F+"};

=== removed file 'scripts/debian/yade32x32.xpm'
--- scripts/debian/yade32x32.xpm	2011-02-08 07:37:09 +0000
+++ scripts/debian/yade32x32.xpm	1970-01-01 00:00:00 +0000
@@ -1,968 +0,0 @@
-/* XPM */
-static char * yade32x32_xpm[] = {
-"32 32 933 2",
-"  	c None",
-". 	c #FCDCDB",
-"+ 	c #AE9191",
-"@ 	c #848484",
-"# 	c #949494",
-"$ 	c #A6A6A6",
-"% 	c #BAB9BA",
-"& 	c #A8A9A8",
-"* 	c #CECDCE",
-"= 	c #C0C0C0",
-"- 	c #CACACA",
-"; 	c #CCCCCC",
-"> 	c #A9A7A9",
-", 	c #B2B2B2",
-"' 	c #C7C7C7",
-") 	c #B7B6B7",
-"! 	c #BCBCBC",
-"~ 	c #C5C4C5",
-"{ 	c #D1CFD1",
-"] 	c #C7C6C7",
-"^ 	c #D9D9D9",
-"/ 	c #E6E6E6",
-"( 	c #E3E4E3",
-"_ 	c #D4D5D4",
-": 	c #BFBFBF",
-"< 	c #D0D1D0",
-"[ 	c #D2D3D2",
-"} 	c #DDDDDD",
-"| 	c #E2E2E2",
-"1 	c #E6E5E6",
-"2 	c #E3E3E3",
-"3 	c #DADADA",
-"4 	c #FB9A9A",
-"5 	c #E48383",
-"6 	c #808483",
-"7 	c #A5A6A5",
-"8 	c #A0A0A0",
-"9 	c #D0CED0",
-"0 	c #A8AAA8",
-"a 	c #B0B1B0",
-"b 	c #E0E0E0",
-"c 	c #ABA9AB",
-"d 	c #B3B3B3",
-"e 	c #ADADAD",
-"f 	c #B5B6B5",
-"g 	c #C7C9C7",
-"h 	c #E2E1E2",
-"i 	c #D3D3D3",
-"j 	c #BEBEBE",
-"k 	c #BDBDBD",
-"l 	c #CDCECD",
-"m 	c #D7D7D7",
-"n 	c #D0D0D0",
-"o 	c #C3C3C3",
-"p 	c #CFCFCF",
-"q 	c #CECECE",
-"r 	c #E1E1E1",
-"s 	c #E7E8E7",
-"t 	c #EAEAEA",
-"u 	c #DCDDDC",
-"v 	c #FA4949",
-"w 	c #FC7F7F",
-"x 	c #FFB0B0",
-"y 	c #D08F8F",
-"z 	c #A1A7A6",
-"A 	c #EEADAE",
-"B 	c #D1ADAD",
-"C 	c #A0A1A0",
-"D 	c #BEBFBE",
-"E 	c #919091",
-"F 	c #D6D6D6",
-"G 	c #959795",
-"H 	c #CDCCCD",
-"I 	c #C6C7C6",
-"J 	c #B3B5B3",
-"K 	c #D4D3D4",
-"L 	c #D5D4D5",
-"M 	c #FFFFFF",
-"N 	c #FEFEFE",
-"O 	c #F3F3F3",
-"P 	c #D5D6D5",
-"Q 	c #FD5252",
-"R 	c #FD9B9B",
-"S 	c #FEDFDF",
-"T 	c #FECBCC",
-"U 	c #F16767",
-"V 	c #FB8485",
-"W 	c #FBDBDB",
-"X 	c #E3BDBE",
-"Y 	c #B8BAB9",
-"Z 	c #B1AFB1",
-"` 	c #C0C1C0",
-" .	c #B9B9B9",
-"..	c #C1C1C1",
-"+.	c #9E9F9E",
-"@.	c #CFCDCF",
-"#.	c #B7B8B7",
-"$.	c #D2D2D2",
-"%.	c #F1F1F1",
-"&.	c #C5C5C5",
-"*.	c #CECFCE",
-"=.	c #DBDADB",
-"-.	c #FBFBFB",
-";.	c #FE6161",
-">.	c #FE9796",
-",.	c #FEB4B4",
-"'.	c #FEACAC",
-").	c #F85E5E",
-"!.	c #EE7676",
-"~.	c #E78E8E",
-"{.	c #DA8384",
-"].	c #999B9D",
-"^.	c #878788",
-"/.	c #C7C8C9",
-"(.	c #ACAEAE",
-"_.	c #BFBEBF",
-":.	c #A8A8A8",
-"<.	c #B0AFB0",
-"[.	c #A3A5A3",
-"}.	c #BDBEBD",
-"|.	c #C3C4C3",
-"1.	c #B4B3B4",
-"2.	c #BFC0BF",
-"3.	c #A4A5A4",
-"4.	c #F9F9F9",
-"5.	c #FE3031",
-"6.	c #FE6868",
-"7.	c #FEBCBC",
-"8.	c #FFB1B1",
-"9.	c #D35A5A",
-"0.	c #CE0A0A",
-"a.	c #000000",
-"b.	c #5C5500",
-"c.	c #525200",
-"d.	c #515000",
-"e.	c #595900",
-"f.	c #545300",
-"g.	c #1B1B22",
-"h.	c #C3C2C3",
-"i.	c #D3D1D3",
-"j.	c #9D9E9D",
-"k.	c #9A9B9A",
-"l.	c #B9BAB9",
-"m.	c #BABBBA",
-"n.	c #7A7B7C",
-"o.	c #353500",
-"p.	c #505000",
-"q.	c #5F5E00",
-"r.	c #525203",
-"s.	c #545400",
-"t.	c #252500",
-"u.	c #4D4D4D",
-"v.	c #E2E3E3",
-"w.	c #FCFCFC",
-"x.	c #FE3333",
-"y.	c #FD7F80",
-"z.	c #FEB8B8",
-"A.	c #FDBDBD",
-"B.	c #FE9696",
-"C.	c #FFDBDB",
-"D.	c #4D3B40",
-"E.	c #7A7B00",
-"F.	c #A4A400",
-"G.	c #B1B000",
-"H.	c #979800",
-"I.	c #A8A900",
-"J.	c #3C3C00",
-"K.	c #818181",
-"L.	c #AAABAA",
-"M.	c #B4B4B4",
-"N.	c #BCBDBC",
-"O.	c #CBCCCB",
-"P.	c #232308",
-"Q.	c #CDCB02",
-"R.	c #E7E71E",
-"S.	c #DFDE0D",
-"T.	c #DEDD02",
-"U.	c #DADA03",
-"V.	c #1A1A18",
-"W.	c #DEDEDE",
-"X.	c #CDCCCE",
-"Y.	c #B6B6B8",
-"Z.	c #CBCACC",
-"`.	c #F25050",
-" +	c #FE4949",
-".+	c #FD6D6D",
-"++	c #FE6D6D",
-"@+	c #E8A2A2",
-"#+	c #F9ACAC",
-"$+	c #E5A6A6",
-"%+	c #14140D",
-"&+	c #BAB902",
-"*+	c #CACA02",
-"=+	c #CCCE07",
-"-+	c #A8AA0A",
-";+	c #0E0E0D",
-">+	c #B0B0B0",
-",+	c #ACACAC",
-"'+	c #BBBABB",
-")+	c #CAC9CA",
-"!+	c #C9C8C9",
-"~+	c #C8C7C8",
-"{+	c #3F3F49",
-"]+	c #A7A800",
-"^+	c #C3C100",
-"/+	c #D7D700",
-"(+	c #E3E203",
-"_+	c #F0F010",
-":+	c #343400",
-"<+	c #A5A4A6",
-"[+	c #C4C4C5",
-"}+	c #CAC9CB",
-"|+	c #CFCFD0",
-"1+	c #D7D7D9",
-"2+	c #DDAAAA",
-"3+	c #F82E2E",
-"4+	c #FE6E6E",
-"5+	c #F39494",
-"6+	c #E1D0D0",
-"7+	c #E89797",
-"8+	c #CAA5A5",
-"9+	c #806C6C",
-"0+	c #6A5816",
-"a+	c #B9B900",
-"b+	c #B9B903",
-"c+	c #C0C101",
-"d+	c #B9BA07",
-"e+	c #787802",
-"f+	c #2F2F34",
-"g+	c #979697",
-"h+	c #C1BFC1",
-"i+	c #8C8B8C",
-"j+	c #484800",
-"k+	c #CDCC00",
-"l+	c #B7B700",
-"m+	c #D1CF05",
-"n+	c #D6D50D",
-"o+	c #878700",
-"p+	c #47474D",
-"q+	c #B8B8B9",
-"r+	c #D5D6D6",
-"s+	c #CBCBCE",
-"t+	c #F7F7F7",
-"u+	c #E95656",
-"v+	c #FF6767",
-"w+	c #FDB1B1",
-"x+	c #FEE5E5",
-"y+	c #EDB3B3",
-"z+	c #E08E8E",
-"A+	c #F35E5E",
-"B+	c #FF8181",
-"C+	c #FFCDD0",
-"D+	c #F9BF86",
-"E+	c #C0A100",
-"F+	c #C5B300",
-"G+	c #DCDE15",
-"H+	c #ADAE00",
-"I+	c #2D2D00",
-"J+	c #707070",
-"K+	c #858485",
-"L+	c #C1BEC1",
-"M+	c #C4C2C4",
-"N+	c #1B1A16",
-"O+	c #CBCB02",
-"P+	c #DEDD15",
-"Q+	c #C4C404",
-"R+	c #BABB00",
-"S+	c #CACB07",
-"T+	c #0D0D0A",
-"U+	c #AAAAAB",
-"V+	c #BFC0C1",
-"W+	c #B7B7BA",
-"X+	c #C8C8CC",
-"Y+	c #E3E2E5",
-"Z+	c #D8D6DA",
-"`+	c #F52222",
-" @	c #FD7B7B",
-".@	c #FEA6A6",
-"+@	c #FDC3C3",
-"@@	c #FA9A9A",
-"#@	c #DB6060",
-"$@	c #FF403F",
-"%@	c #FE9393",
-"&@	c #FECACA",
-"*@	c #FDC2CA",
-"=@	c #FEA30D",
-"-@	c #FDE400",
-";@	c #D2BB00",
-">@	c #A2A200",
-",@	c #BCBD08",
-"'@	c #080707",
-")@	c #848284",
-"!@	c #7C7B7C",
-"~@	c #494850",
-"{@	c #8C8B00",
-"]@	c #C3C306",
-"^@	c #C5C607",
-"/@	c #C4C403",
-"(@	c #E4E41B",
-"_@	c #2D2E00",
-":@	c #7B7B7C",
-"<@	c #949697",
-"[@	c #D3D2D6",
-"}@	c #BCBBC0",
-"|@	c #B1B1B6",
-"1@	c #DFDEE1",
-"2@	c #FB3B3B",
-"3@	c #FE504F",
-"4@	c #FE6F70",
-"5@	c #FE7E7D",
-"6@	c #F86565",
-"7@	c #EF6C6C",
-"8@	c #FE2626",
-"9@	c #FE7575",
-"0@	c #FE8888",
-"a@	c #FF8888",
-"b@	c #734912",
-"c@	c #FFB716",
-"d@	c #E3A600",
-"e@	c #A7AA00",
-"f@	c #AFAE00",
-"g@	c #6F6F03",
-"h@	c #3E3F44",
-"i@	c #787777",
-"j@	c #292900",
-"k@	c #C4C300",
-"l@	c #D9D704",
-"m@	c #C9C800",
-"n@	c #939306",
-"o@	c #393940",
-"p@	c #909193",
-"q@	c #96969B",
-"r@	c #B4B3B8",
-"s@	c #CAC9CD",
-"t@	c #C1C0C5",
-"u@	c #C2C1C7",
-"v@	c #D8D7DC",
-"w@	c #E64A4A",
-"x@	c #FE3030",
-"y@	c #FD2121",
-"z@	c #FE4141",
-"A@	c #FE8C8C",
-"B@	c #FED6D6",
-"C@	c #FE6B6B",
-"D@	c #FE1A1A",
-"E@	c #FE3A3A",
-"F@	c #FD4A4A",
-"G@	c #FF7F81",
-"H@	c #FDB0B7",
-"I@	c #F8C2B2",
-"J@	c #BFAA0A",
-"K@	c #BAB904",
-"L@	c #CCCB02",
-"M@	c #272703",
-"N@	c #17171B",
-"O@	c #939400",
-"P@	c #B3B400",
-"Q@	c #A9AA00",
-"R@	c #C6C500",
-"S@	c #C4C302",
-"T@	c #090909",
-"U@	c #A6A6A9",
-"V@	c #CAC7CC",
-"W@	c #CECED1",
-"X@	c #AFAEB4",
-"Y@	c #9C9BA3",
-"Z@	c #B7B6BD",
-"`@	c #AAAAB2",
-" #	c #FF8484",
-".#	c #FECFCF",
-"+#	c #FEB0B1",
-"@#	c #FD3F3F",
-"##	c #FE9897",
-"$#	c #FEC8C8",
-"%#	c #FEB2B2",
-"&#	c #FE7C7C",
-"*#	c #FE8081",
-"=#	c #FE494A",
-"-#	c #FE8D8E",
-";#	c #FEC7C7",
-">#	c #FDEAE9",
-",#	c #FEB07E",
-"'#	c #C9C101",
-")#	c #E1E211",
-"!#	c #BFC00F",
-"~#	c #787700",
-"{#	c #B6B605",
-"]#	c #B5B506",
-"^#	c #B0B114",
-"/#	c #AFB103",
-"(#	c #848487",
-"_#	c #B8B8BB",
-":#	c #B7B5BB",
-"<#	c #D0D0D3",
-"[#	c #DDDCDF",
-"}#	c #D1CFD5",
-"|#	c #C1C0C7",
-"1#	c #D5D5DA",
-"2#	c #FE9292",
-"3#	c #FEC9C9",
-"4#	c #FDCAC9",
-"5#	c #FE3838",
-"6#	c #FD6969",
-"7#	c #FE7E7E",
-"8#	c #FE7474",
-"9#	c #FE8C8B",
-"0#	c #FE5A5A",
-"a#	c #FE5959",
-"b#	c #FE9191",
-"c#	c #FEABAB",
-"d#	c #FEBBBB",
-"e#	c #FE989E",
-"f#	c #FDB700",
-"g#	c #C5C506",
-"h#	c #BDBD00",
-"i#	c #F6F416",
-"j#	c #D3D415",
-"k#	c #ACAD00",
-"l#	c #C0C108",
-"m#	c #888804",
-"n#	c #2B2A33",
-"o#	c #9F9FA4",
-"p#	c #CECDD1",
-"q#	c #C3C0C7",
-"r#	c #B3B1BB",
-"s#	c #C1C0C8",
-"t#	c #D3D2D8",
-"u#	c #FE8989",
-"v#	c #FF8686",
-"w#	c #EE5353",
-"x#	c #FE1212",
-"y#	c #FD2A2A",
-"z#	c #FE2A2B",
-"A#	c #FE5353",
-"B#	c #FE4747",
-"C#	c #FE6767",
-"D#	c #FE7777",
-"E#	c #FD8080",
-"F#	c #FB725C",
-"G#	c #C69F00",
-"H#	c #B8B901",
-"I#	c #BABB03",
-"J#	c #A0A102",
-"K#	c #DBDA10",
-"L#	c #070706",
-"M#	c #908E94",
-"N#	c #9A9BA1",
-"O#	c #B7B7BB",
-"P#	c #B6B4BC",
-"Q#	c #CCCAD0",
-"R#	c #ADACB7",
-"S#	c #D5D4DA",
-"T#	c #C3C2CB",
-"U#	c #C9C8D0",
-"V#	c #FD2424",
-"W#	c #FD4141",
-"X#	c #F44545",
-"Y#	c #DE8888",
-"Z#	c #E1B4B4",
-"`#	c #F37D7D",
-" $	c #FE9C9C",
-".$	c #FE9999",
-"+$	c #FE4343",
-"@$	c #FD0606",
-"#$	c #FE2222",
-"$$	c #FE3F3E",
-"%$	c #FF4545",
-"&$	c #4B1A13",
-"*$	c #ABAF00",
-"=$	c #B1B201",
-"-$	c #C4C608",
-";$	c #D0D010",
-">$	c #A1A104",
-",$	c #404000",
-"'$	c #444449",
-")$	c #8E8C94",
-"!$	c #8D8C96",
-"~$	c #A7A5AF",
-"{$	c #F1EEF3",
-"]$	c #BCBAC3",
-"^$	c #C1BFC8",
-"/$	c #B3B2BE",
-"($	c #FB2B2B",
-"_$	c #FC6565",
-":$	c #F36262",
-"<$	c #DE4140",
-"[$	c #FD5959",
-"}$	c #FD7F7F",
-"|$	c #FEE8E8",
-"1$	c #FF7373",
-"2$	c #FE4B4C",
-"3$	c #F54041",
-"4$	c #FE6061",
-"5$	c #AB6D6D",
-"6$	c #4A3A00",
-"7$	c #DEC004",
-"8$	c #999E0A",
-"9$	c #8F9603",
-"0$	c #A5AA07",
-"a$	c #838407",
-"b$	c #1C1C24",
-"c$	c #727178",
-"d$	c #9F9CA6",
-"e$	c #95949F",
-"f$	c #CECAD3",
-"g$	c #A7A5B1",
-"h$	c #CBC9D2",
-"i$	c #D0CED7",
-"j$	c #BDBBC7",
-"k$	c #FC3838",
-"l$	c #FC7575",
-"m$	c #FC8D8D",
-"n$	c #F63F3F",
-"o$	c #FE5252",
-"p$	c #FEB3B3",
-"q$	c #FED7D7",
-"r$	c #FEC1C1",
-"s$	c #F47A7A",
-"t$	c #FB7B7B",
-"u$	c #FE3F3F",
-"v$	c #FD7E7E",
-"w$	c #FFC7C7",
-"x$	c #1A1B14",
-"y$	c #FFCA01",
-"z$	c #D89302",
-"A$	c #FDA103",
-"B$	c #F8CA04",
-"C$	c #564E00",
-"D$	c #56545B",
-"E$	c #9D9DA4",
-"F$	c #9895A0",
-"G$	c #95949E",
-"H$	c #9C9BA6",
-"I$	c #92919D",
-"J$	c #8D8C9A",
-"K$	c #A3A2AF",
-"L$	c #A6A6B2",
-"M$	c #AEAEBA",
-"N$	c #B3B2BF",
-"O$	c #B4B2C0",
-"P$	c #FC3232",
-"Q$	c #FC4B4A",
-"R$	c #FC5252",
-"S$	c #FB4646",
-"T$	c #FE4545",
-"U$	c #FE8282",
-"V$	c #FD9292",
-"W$	c #FEA1A1",
-"X$	c #FF9596",
-"Y$	c #D46161",
-"Z$	c #E36D6D",
-"`$	c #FF3232",
-" %	c #FD8687",
-".%	c #FFABAB",
-"+%	c #1E1B12",
-"@%	c #FFBA02",
-"#%	c #F48104",
-"$%	c #F6AC04",
-"%%	c #F7D706",
-"&%	c #625700",
-"*%	c #88878D",
-"=%	c #B2AFB9",
-"-%	c #9E9BA7",
-";%	c #B3B2BC",
-">%	c #9F9CAC",
-",%	c #C4C2CD",
-"'%	c #C3C3CE",
-")%	c #A3A2B2",
-"!%	c #908FA3",
-"~%	c #FC0201",
-"{%	c #FB0D0D",
-"]%	c #FC1111",
-"^%	c #F81919",
-"/%	c #FB5858",
-"(%	c #FB6767",
-"_%	c #FE5B5B",
-":%	c #FF6565",
-"<%	c #BA5656",
-"[%	c #C86464",
-"}%	c #F91515",
-"|%	c #FD5656",
-"1%	c #FF7273",
-"2%	c #1E140B",
-"3%	c #FB9003",
-"4%	c #F36905",
-"5%	c #F49407",
-"6%	c #F6A308",
-"7%	c #624503",
-"8%	c #B9B7BF",
-"9%	c #9A96A4",
-"0%	c #A7A6B2",
-"a%	c #9A98A5",
-"b%	c #9895A7",
-"c%	c #A09EAE",
-"d%	c #AEADBB",
-"e%	c #8B8B9B",
-"f%	c #75738B",
-"g%	c #F20B0B",
-"h%	c #F51313",
-"i%	c #F41C1C",
-"j%	c #FC2728",
-"k%	c #FC6C6C",
-"l%	c #FC8484",
-"m%	c #FE3C3C",
-"n%	c #FD4242",
-"o%	c #FD6F6E",
-"p%	c #FFA5A5",
-"q%	c #FFCDCC",
-"r%	c #FC7E7E",
-"s%	c #FB090B",
-"t%	c #FF2D31",
-"u%	c #220B05",
-"v%	c #CA9306",
-"w%	c #F3680A",
-"x%	c #F35308",
-"y%	c #F8660A",
-"z%	c #5B3001",
-"A%	c #C5C4CC",
-"B%	c #908C9C",
-"C%	c #8B8997",
-"D%	c #C9C7D1",
-"E%	c #757286",
-"F%	c #9695A7",
-"G%	c #9F9DAF",
-"H%	c #B3B0BF",
-"I%	c #878599",
-"J%	c #535366",
-"K%	c #9795AB",
-"L%	c #E03334",
-"M%	c #E05454",
-"N%	c #EE3333",
-"O%	c #FC1616",
-"P%	c #FC3535",
-"Q%	c #FC3B3B",
-"R%	c #E45B5B",
-"S%	c #FF3C3C",
-"T%	c #FE7F7F",
-"U%	c #FDEAEA",
-"V%	c #FDD7D7",
-"W%	c #F57273",
-"X%	c #FF6769",
-"Y%	c #845755",
-"Z%	c #FF940B",
-"`%	c #F49B09",
-" &	c #F29A0A",
-".&	c #CB7809",
-"+&	c #574300",
-"@&	c #8D777F",
-"#&	c #9898A3",
-"$&	c #9D9AA9",
-"%&	c #908F9E",
-"&&	c #9493A3",
-"*&	c #ACA9B9",
-"=&	c #C5C3CF",
-"-&	c #B4B1C1",
-";&	c #9C98AE",
-">&	c #C7C5D0",
-",&	c #777491",
-"'&	c #CDCAD7",
-")&	c #E12121",
-"!&	c #E02F2F",
-"~&	c #E23333",
-"{&	c #F90000",
-"]&	c #FC0000",
-"^&	c #F60F0F",
-"/&	c #F64F4F",
-"(&	c #FE4948",
-"_&	c #FE8A8A",
-":&	c #FDA5A6",
-"<&	c #FDC1C1",
-"[&	c #FB9092",
-"}&	c #FB5F63",
-"|&	c #FA9C9F",
-"1&	c #FDCDCF",
-"2&	c #FBCDCD",
-"3&	c #F09211",
-"4&	c #F0980C",
-"5&	c #F28D0D",
-"6&	c #5D3801",
-"7&	c #BC8188",
-"8&	c #DCA6AE",
-"9&	c #8D899B",
-"0&	c #8A8092",
-"a&	c #B399A9",
-"b&	c #9F98AB",
-"c&	c #9390A5",
-"d&	c #A09DB2",
-"e&	c #AFADBF",
-"f&	c #938FA8",
-"g&	c #9C99AF",
-"h&	c #CFCCDA",
-"i&	c #E02E2E",
-"j&	c #E00D0D",
-"k&	c #E00D0C",
-"l&	c #F80606",
-"m&	c #FC3636",
-"n&	c #FC7878",
-"o&	c #FB8080",
-"p&	c #FC6C6D",
-"q&	c #FC7D7F",
-"r&	c #FB9193",
-"s&	c #F9353A",
-"t&	c #F9757A",
-"u&	c #FBA6A8",
-"v&	c #FCDADB",
-"w&	c #FCDDDF",
-"x&	c #F19E6A",
-"y&	c #EE8C0C",
-"z&	c #EF700F",
-"A&	c #5D3601",
-"B&	c #BC959B",
-"C&	c #FCDBDE",
-"D&	c #D77D8B",
-"E&	c #F56473",
-"F&	c #F7B1B8",
-"G&	c #F7D5D9",
-"H&	c #A89CAC",
-"I&	c #9290A6",
-"J&	c #AFABBE",
-"K&	c #9C99B0",
-"L&	c #9794AD",
-"M&	c #B2AFC3",
-"N&	c #E06969",
-"O&	c #E16E6E",
-"P&	c #E80808",
-"Q&	c #FC0E0F",
-"R&	c #FC4747",
-"S&	c #FC7676",
-"T&	c #FC8383",
-"U&	c #FB3434",
-"V&	c #FB2B2E",
-"W&	c #FA464A",
-"X&	c #FA5155",
-"Y&	c #F82D33",
-"Z&	c #F97D82",
-"`&	c #F9989D",
-" *	c #FAAFB2",
-".*	c #FAB1B4",
-"+*	c #EE8B79",
-"@*	c #D27E09",
-"#*	c #E46110",
-"$*	c #5C3603",
-"%*	c #BA6D76",
-"&*	c #F699A2",
-"**	c #E95667",
-"=*	c #EE7785",
-"-*	c #F3A3AD",
-";*	c #F6C6CC",
-">*	c #F1A6B1",
-",*	c #A8A7BA",
-"'*	c #9F9DB2",
-")*	c #9390AB",
-"!*	c #8F8BA7",
-"~*	c #E16C6C",
-"{*	c #E07070",
-"]*	c #EA2D2D",
-"^*	c #FC0A0A",
-"/*	c #FC3635",
-"(*	c #FC4646",
-"_*	c #FB4C4C",
-":*	c #FB4141",
-"<*	c #FA292C",
-"[*	c #EE161C",
-"}*	c #F4373D",
-"|*	c #F61820",
-"1*	c #F7535A",
-"2*	c #F86C73",
-"3*	c #F87B82",
-"4*	c #F77C84",
-"5*	c #D56A49",
-"6*	c #A8690B",
-"7*	c #DC6C11",
-"8*	c #5F1D06",
-"9*	c #B53442",
-"0*	c #ED4E5F",
-"a*	c #D7485C",
-"b*	c #F28793",
-"c*	c #F5B1BA",
-"d*	c #F5A8B2",
-"e*	c #CF8194",
-"f*	c #A6A4B9",
-"g*	c #A5A3B9",
-"h*	c #A2A0B8",
-"i*	c #B2B0C4",
-"j*	c #E14646",
-"k*	c #E14848",
-"l*	c #E53333",
-"m*	c #FB0303",
-"n*	c #FB0E0E",
-"o*	c #FD0E0E",
-"p*	c #EE4E52",
-"q*	c #FD7D81",
-"r*	c #DA5359",
-"s*	c #FB7C81",
-"t*	c #F8767B",
-"u*	c #F30A16",
-"v*	c #F4343E",
-"w*	c #F34651",
-"x*	c #EB3E4B",
-"y*	c #1D1502",
-"z*	c #211B00",
-"A*	c #211F00",
-"B*	c #B33C4B",
-"C*	c #ED4E60",
-"D*	c #EF5F70",
-"E*	c #F49BA6",
-"F*	c #F9D6DA",
-"G*	c #FAE4E7",
-"H*	c #EF9AA7",
-"I*	c #7A7C96",
-"J*	c #9390AD",
-"K*	c #E01919",
-"L*	c #E81818",
-"M*	c #E52727",
-"N*	c #F85859",
-"O*	c #F90F0F",
-"P*	c #F40202",
-"Q*	c #F72222",
-"R*	c #EE5F61",
-"S*	c #DF686D",
-"T*	c #E2373F",
-"U*	c #F98B90",
-"V*	c #FBC0C3",
-"W*	c #F8848B",
-"X*	c #EB2533",
-"Y*	c #E7424F",
-"Z*	c #E47480",
-"`*	c #FF5765",
-" =	c #FF97A1",
-".=	c #FFD2D8",
-"+=	c #FFF9FB",
-"@=	c #F9B5BD",
-"#=	c #E63349",
-"$=	c #EF7181",
-"%=	c #F39BA6",
-"&=	c #F6BCC4",
-"*=	c #F6C4CC",
-"==	c #F497A5",
-"-=	c #856E86",
-";=	c #B38AA4",
-">=	c #B79FB6",
-",=	c #A19FB9",
-"'=	c #9E9BB5",
-")=	c #FA0000",
-"!=	c #FF0000",
-"~=	c #FF2F2E",
-"{=	c #F35557",
-"]=	c #F80E0D",
-"^=	c #FB7777",
-"/=	c #FB8283",
-"(=	c #DF222A",
-"_=	c #F65961",
-":=	c #F7737B",
-"<=	c #F5747D",
-"[=	c #D01A2A",
-"}=	c #D64959",
-"|=	c #E73243",
-"1=	c #F26673",
-"2=	c #F596A0",
-"3=	c #F7B9C0",
-"4=	c #F9D0D5",
-"5=	c #F6B4BC",
-"6=	c #E82C44",
-"7=	c #ED5B6F",
-"8=	c #EF7C8C",
-"9=	c #F08A9A",
-"0=	c #F08E9E",
-"a=	c #E66F84",
-"b=	c #C16984",
-"c=	c #ED8194",
-"d=	c #F9DBE0",
-"e=	c #BEA2B6",
-"f=	c #9D9AB5",
-"g=	c #FF0505",
-"h=	c #FF5555",
-"i=	c #FE8484",
-"j=	c #FB1F20",
-"k=	c #FC5151",
-"l=	c #FC8282",
-"m=	c #FB9190",
-"n=	c #D94B4D",
-"o=	c #D20C18",
-"p=	c #E82835",
-"q=	c #DA4856",
-"r=	c #DF6874",
-"s=	c #D85160",
-"t=	c #E6192D",
-"u=	c #F05968",
-"v=	c #F3818E",
-"w=	c #F48F9B",
-"x=	c #F49AA5",
-"y=	c #F18896",
-"z=	c #E73F57",
-"A=	c #E41734",
-"B=	c #E73F58",
-"C=	c #E9546B",
-"D=	c #EA556D",
-"E=	c #D2617B",
-"F=	c #BC4063",
-"G=	c #E98296",
-"H=	c #EEA3B2",
-"I=	c #EA93A4",
-"J=	c #8585A6",
-"K=	c #FE0000",
-"L=	c #FF0202",
-"M=	c #FF2726",
-"N=	c #FF0B0B",
-"O=	c #FB2727",
-"P=	c #FC5B5B",
-"Q=	c #FC6161",
-"R=	c #FB4849",
-"S=	c #B95C65",
-"T=	c #D52736",
-"U=	c #DE5F6D",
-"V=	c #E08792",
-"W=	c #E1A1AA",
-"X=	c #E16675",
-"Y=	c #EB1B32",
-"Z=	c #ED4558",
-"`=	c #ED596C",
-" -	c #EE6374",
-".-	c #EA4D62",
-"+-	c #ED8090",
-"@-	c #E8566D",
-"#-	c #E11C3B",
-"$-	c #E12A49",
-"%-	c #C54464",
-"&-	c #DC6A84",
-"*-	c #EC798E",
-"=-	c #E4506C",
-"--	c #E24562",
-";-	c #AD6687",
-">-	c #7F7B9F",
-". + @ # $ % & * = - ; > , ' ) ! ~ { ] ] ^ / ( _ : < [ } | 1 2 3 ",
-"4 5   6 7 8 9 0 a b c d e f ~ g h i j k ' l m n o p q r s t u r ",
-"v w x y z A B C D i E F o G H   I m J = K 1 ; F ~ L = M N O P r ",
-"Q R S T U V W X Y Z `    ...+.@.  #.D p ..$.%.n : %.&.*.M - =.-.",
-";.>.,.'.).!.~.{.].^./.(.  _.:.<.F [.}.|. .t ] 1.2.P ~ 3.}.*.4.N ",
-"5.6.7.8.9.0.a.b.c.d.e.f.g.h.i.j.k.l.  i m.n.o.p.q.r.s.t.u.v.w.M ",
-"x.y.z.A.B.C.D.E.F.G.H.I.J.K.! L.M.N._.p O.P.Q.R.S.T.U.V.W.X.Y.Z.",
-"`. +.+++@+#+$+%+  &+*+=+-+;+>+,+'+)+!+~+{+]+^+/+(+_+:+<+[+}+|+1+",
-"2+3+4+5+6+7+8+9+0+a+b+c+d+e+f+g+)+h+  i+j+k+l+m+n+o+p+q+r+s+t+N ",
-"u+v+w+x+y+z+A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z+",
-"`+ @.@+@@@#@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@/@(@_@:@<@[@}@|@1@  ",
-"2@3@4@5@6@7@8@9@0@a@b@c@d@e@f@g@h@i@j@l+k@l@m@n@o@p@q@r@s@t@u@v@",
-"w@x@y@z@A@B@C@D@E@F@G@H@I@J@K@L@M@N@O@P@Q@R@S@T@U@V@W@X@Y@Z@`@u@",
-" #.#+#@###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]#^#/#o.(#_#:#<#[#  }#|#1#",
-"2#3#4#5#6#7#8#9#0#a#b#c#d#e#f#g#h#i#j#k#l#m#n#o#p#q#      r#s#t#",
-"8#u#v#w#x#y#z#A#B#x.C#D#E#F#G#H#  H#I#J#K#L#M#N#O#P#Q#  R#S#T#U#",
-"V#W#X#Y#Z#`# $.$+$@$#$$$%$&$*$=$k#-$;$>$,$'$)$  !$~${$]$^$    /$",
-"($_$:$<$[$}$z.|$A.1$2$3$4$5$6$7$8$9$0$a$b$c$d$    e$f$g$  h$i$j$",
-"k$l$m$n$o$-#p$q$r$s$t$u$v$w$x$y$z$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$",
-"P$Q$R$S$T$U$V$W$X$Y$Z$`$ %.%+%@%#%$%%%&%*%=%-%    ;%>%,%  '%)%!%",
-"~%{%]%^%/%(%_%C@:%<%[%}%|%1%2%3%4%5%6%7%  8%9%  0%a%  b%c%d%e%f%",
-"g%h%i%j%k%l%m%n%o%p%q%r%s%t%u%v%w%x%y%z%  A%B%C%D%E%F%G%H%I%J%K%",
-"L%M%N%O%P%Q%R%S%T%p$U%V%W%X%Y%Z%`% &.&+&@&#&$&%&&&*&=&-&;&>&,&'&",
-")&!&~&{&]&^&/&(&_&:&<&[&}&|&1&2&3&4&5&6&7&8&9&0&a&b&c&d&e&f&g&h&",
-"i&j&k&l&m&n&o&P%p&q&r&s&t&u&v&w&x&y&z&A&B&C&D&E&F&G&H&I&J&K&L&M&",
-"N&O&P&Q&R&S&T&U&V&W&X&Y&Z&`& *.*+*@*#*$*%*&***=*-*;*>*,*'*  )*!*",
-"~*{*]*^*/*(*_*:*<*[*}*|*1*2*3*4*5*6*7*8*9*0*a*b*c*d*e*f*  g*h*i*",
-"j*k*l*]&m*n*o*p*q*r*s*t*u*v*w*x*y*z*A*a.B*C*D*E*F*G*H*I*      J*",
-"K*L*M*N*O*P*Q*R*S*T*U*V*W*X*Y*Z*`* =.=+=@=#=$=%=&=*===-=;=>=,='=",
-")=!=~=2${=]=R&^=/=(=_=:=<=[=}=|=1=2=3=4=5=6=7=8=9=0=a=b=c=d=e=f=",
-"!=g=h=i=#$j=k=l=m=n=o=p=q=r=s=t=u=v=w=x=y=z=A=B=C=D=E=F=G=H=I=J=",
-"K=L=M=S%N=O=(*P=Q=R=S=T=U=V=W=X=Y=Z=`= -.-+-@-#-$-%-&-*-=---;->-"};

=== removed directory 'site_scons'
=== removed directory 'site_scons/site_tools'
=== removed directory 'site_scons/site_tools/qt4'
=== removed file 'site_scons/site_tools/qt4/__init__.py'
--- site_scons/site_tools/qt4/__init__.py	2010-07-23 22:17:33 +0000
+++ site_scons/site_tools/qt4/__init__.py	1970-01-01 00:00:00 +0000
@@ -1,963 +0,0 @@
-
-"""SCons.Tool.qt4
-
-Tool-specific initialization for Qt4.
-
-There normally shouldn't be any need to import this module directly.
-It will usually be imported through the generic SCons.Tool.Tool()
-selection method.
-
-"""
-
-#
-# Copyright (c) 2001-7,2010 The SCons Foundation
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-import os.path
-import re
-
-import SCons.Action
-import SCons.Builder
-import SCons.Defaults
-import SCons.Scanner
-import SCons.Tool
-import SCons.Util
-
-class ToolQt4Warning(SCons.Warnings.Warning):
-    pass
-
-class GeneratedMocFileNotIncluded(ToolQt4Warning):
-    pass
-
-class QtdirNotFound(ToolQt4Warning):
-    pass
-
-SCons.Warnings.enableWarningClass(ToolQt4Warning)
-
-try:
-    sorted
-except NameError:
-    # Pre-2.4 Python has no sorted() function.
-    #
-    # The pre-2.4 Python list.sort() method does not support
-    # list.sort(key=) nor list.sort(reverse=) keyword arguments, so
-    # we must implement the functionality of those keyword arguments
-    # by hand instead of passing them to list.sort().
-    def sorted(iterable, cmp=None, key=None, reverse=0):
-        if key is not None:
-            result = [(key(x), x) for x in iterable]
-        else:
-            result = iterable[:]
-        if cmp is None:
-            # Pre-2.3 Python does not support list.sort(None).
-            result.sort()
-        else:
-            result.sort(cmp)
-        if key is not None:
-            result = [t1 for t0,t1 in result]
-        if reverse:
-            result.reverse()
-        return result
-
-qrcinclude_re = re.compile(r'<file[^>]*>([^<]*)</file>', re.M)
-
-def transformToWinePath(path) :
-    return os.popen('winepath -w "%s"'%path).read().strip().replace('\\','/')
-
-header_extensions = [".h", ".hxx", ".hpp", ".hh"]
-if SCons.Util.case_sensitive_suffixes('.h', '.H'):
-    header_extensions.append('.H')
-# TODO: The following two lines will work when integrated back to SCons
-# TODO: Meanwhile the third line will do the work
-#cplusplus = __import__('c++', globals(), locals(), [])
-#cxx_suffixes = cplusplus.CXXSuffixes
-cxx_suffixes = [".c", ".cxx", ".cpp", ".cc"]
-
-def checkMocIncluded(target, source, env):
-    moc = target[0]
-    cpp = source[0]
-    # looks like cpp.includes is cleared before the build stage :-(
-    # not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/
-    path = SCons.Defaults.CScan.path_function(env, moc.cwd)
-    includes = SCons.Defaults.CScan(cpp, env, path)
-    if not moc in includes:
-        SCons.Warnings.warn(
-            GeneratedMocFileNotIncluded,
-            "Generated moc file '%s' is not included by '%s'" %
-            (str(moc), str(cpp)))
-
-def find_file(filename, paths, node_factory):
-    for dir in paths:
-        node = node_factory(filename, dir)
-        if node.rexists():
-            return node
-    return None
-
-class _Automoc:
-    """
-    Callable class, which works as an emitter for Programs, SharedLibraries and
-    StaticLibraries.
-    """
-
-    def __init__(self, objBuilderName):
-        self.objBuilderName = objBuilderName
-        # some regular expressions:
-        # Q_OBJECT detection
-        self.qo_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]')
-        # cxx and c comment 'eater'
-        self.ccomment = re.compile(r'/\*(.*?)\*/',re.S)
-        self.cxxcomment = re.compile(r'//.*$',re.M)
-        # we also allow Q_OBJECT in a literal string
-        self.literal_qobject = re.compile(r'"[^\n]*Q_OBJECT[^\n]*"')
-        
-    def create_automoc_options(self, env):
-        """
-        Create a dictionary with variables related to Automocing,
-        based on the current environment.
-        Is executed once in the __call__ routine.  
-        """
-        moc_options = {'auto_scan' : True,
-                       'auto_scan_strategy' : 0,
-                       'gobble_comments' : 0,
-                       'debug' : 0,
-                       'auto_cpppath' : True,
-                       'cpppaths' : []}
-        try:
-            if int(env.subst('$QT4_AUTOSCAN')) == 0:
-                moc_options['auto_scan'] = False
-        except ValueError:
-            pass
-        try:
-            moc_options['auto_scan_strategy'] = int(env.subst('$QT4_AUTOSCAN_STRATEGY'))
-        except ValueError:
-            pass
-        try:
-            moc_options['gobble_comments'] = int(env.subst('$QT4_GOBBLECOMMENTS'))
-        except ValueError:
-            pass
-        try:
-            moc_options['debug'] = int(env.subst('$QT4_DEBUG'))
-        except ValueError:
-            pass
-        try:
-            if int(env.subst('$QT4_AUTOMOC_SCANCPPPATH')) == 0:
-                moc_options['auto_cpppath'] = False
-        except ValueError:
-            pass
-        if moc_options['auto_cpppath']:
-            paths = env.get('QT4_AUTOMOC_CPPPATH', [])
-            if not paths:
-                paths = env.get('CPPPATH', [])
-            moc_options['cpppaths'].extend(paths)
-        
-        return moc_options
-
-    def __automoc_strategy_simple(self, env, moc_options, 
-                                  cpp, cpp_contents, out_sources):
-        """
-        Default Automoc strategy (Q_OBJECT driven): detect a header file
-        (alongside the current cpp/cxx) that contains a Q_OBJECT
-        macro...and MOC it.
-        If a Q_OBJECT macro is also found in the cpp/cxx itself,
-        it gets MOCed too.
-        """
-        
-        h=None
-        for h_ext in header_extensions:
-            # try to find the header file in the corresponding source
-            # directory
-            hname = self.splitext(cpp.name)[0] + h_ext
-            h = find_file(hname, [cpp.get_dir()]+moc_options['cpppaths'], env.File)
-            if h:
-                if moc_options['debug']:
-                    print "scons: qt4: Scanning '%s' (header of '%s')" % (str(h), str(cpp))
-                h_contents = h.get_contents()
-                if moc_options['gobble_comments']:
-                    h_contents = self.ccomment.sub('', h_contents)
-                    h_contents = self.cxxcomment.sub('', h_contents)
-                h_contents = self.literal_qobject.sub('""', h_contents)
-                break
-        if not h and moc_options['debug']:
-            print "scons: qt4: no header for '%s'." % (str(cpp))
-        if h and self.qo_search.search(h_contents):
-            # h file with the Q_OBJECT macro found -> add moc_cpp
-            moc_cpp = env.Moc4(h)
-            moc_o = self.objBuilder(moc_cpp)
-            out_sources.extend(moc_o)
-            if moc_options['debug']:
-                print "scons: qt4: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(moc_cpp))
-        if cpp and self.qo_search.search(cpp_contents):
-            # cpp file with Q_OBJECT macro found -> add moc
-            # (to be included in cpp)
-            moc = env.Moc4(cpp)
-            env.Ignore(moc, moc)
-            if moc_options['debug']:
-                print "scons: qt4: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc))
-
-    def __automoc_strategy_include_driven(self, env, moc_options,
-                                          cpp, cpp_contents, out_sources):
-        """
-        Automoc strategy #1 (include driven): searches for "include"
-        statements of MOCed files in the current cpp/cxx file.
-        This strategy tries to add support for the compilation
-        of the qtsolutions...
-        """
-        if self.splitext(str(cpp))[1] in cxx_suffixes:
-            added = False
-            h_moc = "%s%s%s" % (env.subst('$QT4_XMOCHPREFIX'),
-                                self.splitext(cpp.name)[0],
-                                env.subst('$QT4_XMOCHSUFFIX'))
-            cxx_moc = "%s%s%s" % (env.subst('$QT4_XMOCCXXPREFIX'),
-                                  self.splitext(cpp.name)[0],
-                                  env.subst('$QT4_XMOCCXXSUFFIX'))
-            inc_h_moc = r'#include\s+"%s"' % h_moc
-            inc_cxx_moc = r'#include\s+"%s"' % cxx_moc
-            
-            # Search for special includes in qtsolutions style
-            if cpp and re.search(inc_h_moc, cpp_contents):
-                # cpp file with #include directive for a MOCed header found -> add moc
-                
-                # Try to find header file                    
-                h=None
-                hname=""
-                for h_ext in header_extensions:
-                    # Try to find the header file in the
-                    # corresponding source directory
-                    hname = self.splitext(cpp.name)[0] + h_ext
-                    h = find_file(hname, [cpp.get_dir()]+moc_options['cpppaths'], env.File)
-                    if h:
-                        if moc_options['debug']:
-                            print "scons: qt4: Scanning '%s' (header of '%s')" % (str(h), str(cpp))
-                        h_contents = h.get_contents()
-                        if moc_options['gobble_comments']:
-                            h_contents = self.ccomment.sub('', h_contents)
-                            h_contents = self.cxxcomment.sub('', h_contents)
-                        h_contents = self.literal_qobject.sub('""', h_contents)
-                        break
-                if not h and moc_options['debug']:
-                    print "scons: qt4: no header for '%s'." % (str(cpp))
-                if h and self.qo_search.search(h_contents):
-                    # h file with the Q_OBJECT macro found -> add moc_cpp
-                    moc_cpp = env.XMoc4(h)
-                    env.Ignore(moc_cpp, moc_cpp)
-                    added = True
-                    # Removing file from list of sources, because it is not to be
-                    # compiled but simply included by the cpp/cxx file.
-                    for idx, s in enumerate(out_sources):
-                        if hasattr(s, "sources") and len(s.sources) > 0:
-                            if str(s.sources[0]) == h_moc:
-                                out_sources.pop(idx)
-                                break
-                    if moc_options['debug']:
-                        print "scons: qt4: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(h), str(h_moc))
-                else:
-                    if moc_options['debug']:
-                        print "scons: qt4: found no Q_OBJECT macro in '%s', but a moc'ed version '%s' gets included in '%s'" % (str(h), inc_h_moc, cpp.name)
-
-            if cpp and re.search(inc_cxx_moc, cpp_contents):
-                # cpp file with #include directive for a MOCed cxx file found -> add moc
-                if self.qo_search.search(cpp_contents):
-                    moc = env.XMoc4(target=cxx_moc, source=cpp)
-                    env.Ignore(moc, moc)
-                    added = True
-                    if moc_options['debug']:
-                        print "scons: qt4: found Q_OBJECT macro in '%s', moc'ing to '%s'" % (str(cpp), str(moc))
-                else:
-                    if moc_options['debug']:
-                        print "scons: qt4: found no Q_OBJECT macro in '%s', although a moc'ed version '%s' of itself gets included" % (cpp.name, inc_cxx_moc)
-
-            if not added:
-                # Fallback to default Automoc strategy (Q_OBJECT driven)
-               self.__automoc_strategy_simple(env, moc_options, cpp,
-                                              cpp_contents, out_sources)
-        
-    def __call__(self, target, source, env):
-        """
-        Smart autoscan function. Gets the list of objects for the Program
-        or Lib. Adds objects and builders for the special qt4 files.
-        """
-        moc_options = self.create_automoc_options(env)
-        
-        # some shortcuts used in the scanner
-        self.splitext = SCons.Util.splitext
-        self.objBuilder = getattr(env, self.objBuilderName)
-
-        # The following is kind of hacky to get builders working properly (FIXME)
-        objBuilderEnv = self.objBuilder.env
-        self.objBuilder.env = env
-        mocBuilderEnv = env.Moc4.env
-        env.Moc4.env = env
-        xMocBuilderEnv = env.XMoc4.env
-        env.XMoc4.env = env
-        
-        # make a deep copy for the result; MocH objects will be appended
-        out_sources = source[:]
-
-        for obj in source:
-            if not moc_options['auto_scan']:
-                break
-            if isinstance(obj,basestring):  # big kludge!
-                print "scons: qt4: '%s' MAYBE USING AN OLD SCONS VERSION AND NOT CONVERTED TO 'File'. Discarded." % str(obj)
-                continue
-            if not obj.has_builder():
-                # binary obj file provided
-                if moc_options['debug']:
-                    print "scons: qt4: '%s' seems to be a binary. Discarded." % str(obj)
-                continue
-            cpp = obj.sources[0]
-            if not self.splitext(str(cpp))[1] in cxx_suffixes:
-                if moc_options['debug']:
-                    print "scons: qt4: '%s' is no cxx file. Discarded." % str(cpp) 
-                # c or fortran source
-                continue
-            try:
-                cpp_contents = cpp.get_contents()
-                if moc_options['gobble_comments']:
-                    cpp_contents = self.ccomment.sub('', cpp_contents)
-                    cpp_contents = self.cxxcomment.sub('', cpp_contents)
-                cpp_contents = self.literal_qobject.sub('""', cpp_contents)
-            except: continue # may be an still not generated source
-            
-            if moc_options['auto_scan_strategy'] == 0:
-                # Default Automoc strategy (Q_OBJECT driven)
-                self.__automoc_strategy_simple(env, moc_options,
-                                               cpp, cpp_contents, out_sources)
-            else:
-                # Automoc strategy #1 (include driven)
-                self.__automoc_strategy_include_driven(env, moc_options,
-                                                       cpp, cpp_contents, out_sources)
-
-        # restore the original env attributes (FIXME)
-        self.objBuilder.env = objBuilderEnv
-        env.Moc4.env = mocBuilderEnv
-        env.XMoc4.env = xMocBuilderEnv
-
-        return (target, sorted(set(out_sources)))
-
-AutomocShared = _Automoc('SharedObject')
-AutomocStatic = _Automoc('StaticObject')
-
-def _detect(env):
-    """Not really safe, but fast method to detect the Qt4 library"""
-    # TODO: check output of "moc -v" for correct version >= 4.0.0
-    try: return env['QT4DIR']
-    except KeyError: pass
-
-    try: return env['QTDIR']
-    except KeyError: pass
-
-    try: return os.environ['QT4DIR']
-    except KeyError: pass
-
-    try: return os.environ['QTDIR']
-    except KeyError: pass
-
-    moc = env.WhereIs('moc-qt4') or env.WhereIs('moc4') or env.WhereIs('moc')
-    if moc:
-        QT4DIR = os.path.dirname(os.path.dirname(moc))
-        SCons.Warnings.warn(
-            QtdirNotFound,
-            "QT4DIR variable is not defined, using moc executable as a hint (QT4DIR=%s)" % QT4DIR)
-        return QT4DIR
-
-    raise SCons.Errors.StopError(
-        QtdirNotFound,
-        "Could not detect Qt 4 installation")
-    return None
-
-
-def __scanResources(node, env, path, arg):
-    # Helper function for scanning .qrc resource files
-    # I've been careful on providing names relative to the qrc file
-    # If that was not needed this code could be simplified a lot
-    def recursiveFiles(basepath, path) :
-        result = []
-        for item in os.listdir(os.path.join(basepath, path)) :
-            itemPath = os.path.join(path, item)
-            if os.path.isdir(os.path.join(basepath, itemPath)) :
-                result += recursiveFiles(basepath, itemPath)
-            else:
-                result.append(itemPath)
-        return result
-    contents = node.get_contents()
-    includes = qrcinclude_re.findall(contents)
-    qrcpath = os.path.dirname(node.path)
-    dirs = [included for included in includes if os.path.isdir(os.path.join(qrcpath,included))]
-    # dirs need to include files recursively
-    for dir in dirs :
-        includes.remove(dir)
-        includes+=recursiveFiles(qrcpath,dir)
-    return includes
-
-#
-# Scanners
-#
-__qrcscanner = SCons.Scanner.Scanner(name = 'qrcfile',
-    function = __scanResources,
-    argument = None,
-    skeys = ['.qrc'])
-
-#
-# Emitters
-#
-def __qrc_path(head, prefix, tail, suffix):
-    if head:
-        if tail:
-            return os.path.join(head, "%s%s%s" % (prefix, tail, suffix))
-        else:
-            return "%s%s%s" % (prefix, head, suffix)
-    else:
-        return "%s%s%s" % (prefix, tail, suffix)
-def __qrc_emitter(target, source, env):
-    sourceBase, sourceExt = os.path.splitext(SCons.Util.to_String(source[0]))
-    sHead = None
-    sTail = sourceBase
-    if sourceBase:
-        sHead, sTail = os.path.split(sourceBase)
-
-    t = __qrc_path(sHead, env.subst('$QT4_QRCCXXPREFIX'),
-                   sTail, env.subst('$QT4_QRCCXXSUFFIX'))
-
-    return t, source
-
-#
-# Action generators
-#
-def __moc_generator_from_h(source, target, env, for_signature):
-    pass_defines = False
-    try:
-        if int(env.subst('$QT4_CPPDEFINES_PASSTOMOC')) == 1:
-            pass_defines = True
-    except ValueError:
-        pass
-    
-    if pass_defines:
-        return '$QT4_MOC $QT4_MOCDEFINES $QT4_MOCFROMHFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE'
-    else:
-        return '$QT4_MOC $QT4_MOCFROMHFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE'
-
-def __moc_generator_from_cxx(source, target, env, for_signature):
-    pass_defines = False
-    try:
-        if int(env.subst('$QT4_CPPDEFINES_PASSTOMOC')) == 1:
-            pass_defines = True
-    except ValueError:
-        pass
-    
-    if pass_defines:
-        return ['$QT4_MOC $QT4_MOCDEFINES $QT4_MOCFROMCXXFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE',
-                SCons.Action.Action(checkMocIncluded,None)]
-    else:
-        return ['$QT4_MOC $QT4_MOCFROMCXXFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE',
-                SCons.Action.Action(checkMocIncluded,None)]
-
-def __mocx_generator_from_h(source, target, env, for_signature):
-    pass_defines = False
-    try:
-        if int(env.subst('$QT4_CPPDEFINES_PASSTOMOC')) == 1:
-            pass_defines = True
-    except ValueError:
-        pass
-    
-    if pass_defines:
-        return '$QT4_MOC $QT4_MOCDEFINES $QT4_MOCFROMHFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE'
-    else:
-        return '$QT4_MOC $QT4_MOCFROMHFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE'
-
-def __mocx_generator_from_cxx(source, target, env, for_signature):
-    pass_defines = False
-    try:
-        if int(env.subst('$QT4_CPPDEFINES_PASSTOMOC')) == 1:
-            pass_defines = True
-    except ValueError:
-        pass
-    
-    if pass_defines:
-        return ['$QT4_MOC $QT4_MOCDEFINES $QT4_MOCFROMCXXFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE',
-                SCons.Action.Action(checkMocIncluded,None)]
-    else:
-        return ['$QT4_MOC $QT4_MOCFROMCXXFLAGS $QT4_MOCINCFLAGS -o $TARGET $SOURCE',
-                SCons.Action.Action(checkMocIncluded,None)]
-
-def __qrc_generator(source, target, env, for_signature):
-    name_defined = False
-    try:
-        if env.subst('$QT4_QRCFLAGS').find('-name') >= 0:
-            name_defined = True
-    except ValueError:
-        pass
-    
-    if name_defined:
-        return '$QT4_RCC $QT4_QRCFLAGS $SOURCE -o $TARGET'
-    else:
-        qrc_suffix = env.subst('$QT4_QRCSUFFIX')
-        src = str(source[0])
-        head, tail = os.path.split(src)
-        if tail:
-            src = tail
-        qrc_suffix = env.subst('$QT4_QRCSUFFIX')
-        if src.endswith(qrc_suffix):
-            qrc_stem = src[:-len(qrc_suffix)]
-        else:
-            qrc_stem = src
-        return '$QT4_RCC $QT4_QRCFLAGS -name %s $SOURCE -o $TARGET' % qrc_stem
-
-#
-# Builders
-#
-__ts_builder = SCons.Builder.Builder(        
-        action = SCons.Action.Action('$QT4_LUPDATECOM','$QT4_LUPDATECOMSTR'),
-        suffix = '.ts',
-        source_factory = SCons.Node.FS.Entry)
-__qm_builder = SCons.Builder.Builder(
-        action = SCons.Action.Action('$QT4_LRELEASECOM','$QT4_LRELEASECOMSTR'),
-        src_suffix = '.ts',
-        suffix = '.qm')
-__qrc_builder = SCons.Builder.Builder(
-        action = SCons.Action.CommandGeneratorAction(__qrc_generator, {}),
-        source_scanner = __qrcscanner,
-        src_suffix = '$QT4_QRCSUFFIX',
-        suffix = '$QT4_QRCCXXSUFFIX',
-        prefix = '$QT4_QRCCXXPREFIX',
-        single_source = 1)
-__ex_moc_builder = SCons.Builder.Builder(
-        action = SCons.Action.CommandGeneratorAction(__moc_generator_from_h, {}))
-__ex_uic_builder = SCons.Builder.Builder(
-        action = SCons.Action.Action('$QT4_UICCOM', '$QT4_UICCOMSTR'),
-        src_suffix = '.ui')
-
-
-#
-# Wrappers (pseudo-Builders)
-#
-def Ts4(env, target, source=None, *args, **kw):
-    """
-    A pseudo-Builder wrapper around the LUPDATE executable of Qt4.
-        lupdate [options] [source-file|path]... -ts ts-files
-    """
-    if not SCons.Util.is_List(target):
-        target = [target]
-    if not source:
-        source = target[:]
-    if not SCons.Util.is_List(source):
-        source = [source]
-
-    # Check QT4_CLEAN_TS and use NoClean() function
-    clean_ts = False
-    try:
-        if int(env.subst('$QT4_CLEAN_TS')) == 1:
-            clean_ts = True
-    except ValueError:
-        pass
-    
-    result = []
-    for t in target:
-        obj = __ts_builder.__call__(env, t, source, **kw)
-        # Prevent deletion of the .ts file, unless explicitly specified
-        if not clean_ts:
-            env.NoClean(obj)
-        # Always make our target "precious", such that it is not deleted
-        # prior to a rebuild
-        env.Precious(obj)
-        # Add to resulting target list        
-        result.extend(obj)
-
-    return result
-
-def Qm4(env, target, source=None, *args, **kw):
-    """
-    A pseudo-Builder wrapper around the LRELEASE executable of Qt4.
-        lrelease [options] ts-files [-qm qm-file]
-    """
-    if not SCons.Util.is_List(target):
-        target = [target]
-    if not source:
-        source = target[:]
-    if not SCons.Util.is_List(source):
-        source = [source]
-
-    result = []    
-    for t in target:
-        result.extend(__qm_builder.__call__(env, t, source, **kw))
-
-    return result
-
-def Qrc4(env, target, source=None, *args, **kw):
-    """
-    A pseudo-Builder wrapper around the RCC executable of Qt4.
-        rcc [options] qrc-files -o out-file
-    """
-    if not SCons.Util.is_List(target):
-        target = [target]
-    if not source:
-        source = target[:]
-    if not SCons.Util.is_List(source):
-        source = [source]
-
-    result = []
-    for t, s in zip(target, source):
-        result.extend(__qrc_builder.__call__(env, t, s, **kw))
-
-    return result
-
-def ExplicitMoc4(env, target, source, *args, **kw):
-    """
-    A pseudo-Builder wrapper around the MOC executable of Qt4.
-        moc [options] <header-file>
-    """
-    if not SCons.Util.is_List(target):
-        target = [target]
-    if not SCons.Util.is_List(source):
-        source = [source]
-
-    result = []
-    for t in target:
-        # Is it a header or a cxx file?
-        result.extend(__ex_moc_builder.__call__(env, t, source, **kw))
-
-    return result
-
-def ExplicitUic4(env, target, source, *args, **kw):
-    """
-    A pseudo-Builder wrapper around the UIC executable of Qt4.
-        uic [options] <uifile>
-    """
-    if not SCons.Util.is_List(target):
-        target = [target]
-    if not SCons.Util.is_List(source):
-        source = [source]
-
-    result = []
-    for t in target:
-        result.extend(__ex_uic_builder.__call__(env, t, source, **kw))
-
-    return result
-
-def generate(env):
-    """Add Builders and construction variables for qt4 to an Environment."""
-
-    def locateQt4Command(env, command, qtdir) :
-        suffixes = [
-            '-qt4',
-            '-qt4.exe',
-            '4',
-            '4.exe',
-            '',
-            '.exe',
-        ]
-        triedPaths = []
-        for suffix in suffixes :
-            fullpath = os.path.join(qtdir,'bin',command + suffix)
-            if os.access(fullpath, os.X_OK) :
-                return fullpath
-            triedPaths.append(fullpath)
-
-        fullpath = env.Detect([command+'-qt4', command+'4', command])
-        if not (fullpath is None) : return fullpath
-
-        raise Exception("Qt4 command '" + command + "' not found. Tried: " + ', '.join(triedPaths))
-
-    CLVar = SCons.Util.CLVar
-    Action = SCons.Action.Action
-    Builder = SCons.Builder.Builder
-
-    env['QT4DIR']  = _detect(env)
-    # TODO: 'Replace' should be 'SetDefault'
-#    env.SetDefault(
-    env.Replace(
-        QT4DIR  = _detect(env),
-        QT4_BINPATH = os.path.join('$QT4DIR', 'bin'),
-        # TODO: This is not reliable to QT4DIR value changes but needed in order to support '-qt4' variants
-        QT4_MOC = locateQt4Command(env,'moc', env['QT4DIR']),
-        QT4_UIC = locateQt4Command(env,'uic', env['QT4DIR']),
-        QT4_RCC = locateQt4Command(env,'rcc', env['QT4DIR']),
-        QT4_LUPDATE = locateQt4Command(env,'lupdate', env['QT4DIR']),
-        QT4_LRELEASE = locateQt4Command(env,'lrelease', env['QT4DIR']),
-
-        QT4_AUTOSCAN = 1, # Should the qt4 tool try to figure out, which sources are to be moc'ed?
-        QT4_AUTOSCAN_STRATEGY = 0, # While scanning for files to moc, should we search for includes in qtsolutions style?
-        QT4_GOBBLECOMMENTS = 0, # If set to 1, comments are removed before scanning cxx/h files.
-        QT4_CPPDEFINES_PASSTOMOC = 1, # If set to 1, all CPPDEFINES get passed to the moc executable.
-        QT4_CLEAN_TS = 0, # If set to 1, translation files (.ts) get cleaned on 'scons -c'
-        QT4_AUTOMOC_SCANCPPPATH = 1, # If set to 1, the CPPPATHs (or QT4_AUTOMOC_CPPPATH) get scanned for moc'able files
-        QT4_AUTOMOC_CPPPATH = [], # Alternative paths that get scanned for moc files
-
-        # Some Qt4 specific flags. I don't expect someone wants to
-        # manipulate those ...
-        QT4_UICFLAGS = CLVar(''),
-        QT4_MOCFROMHFLAGS = CLVar(''),
-        QT4_MOCFROMCXXFLAGS = CLVar('-i'),
-        QT4_QRCFLAGS = '',
-        QT4_LUPDATEFLAGS = '',
-        QT4_LRELEASEFLAGS = '',
-
-        # suffixes/prefixes for the headers / sources to generate
-        QT4_UISUFFIX = '.ui',
-        QT4_UICDECLPREFIX = 'ui_',
-        QT4_UICDECLSUFFIX = '.h',
-        QT4_MOCINCPREFIX = '-I',
-        QT4_MOCHPREFIX = 'moc_',
-        QT4_MOCHSUFFIX = '$CXXFILESUFFIX',
-        QT4_MOCCXXPREFIX = '',
-        QT4_MOCCXXSUFFIX = '.moc',
-        QT4_QRCSUFFIX = '.qrc',
-        QT4_QRCCXXSUFFIX = '$CXXFILESUFFIX',
-        QT4_QRCCXXPREFIX = 'qrc_',
-        QT4_MOCDEFPREFIX = '-D',
-        QT4_MOCDEFSUFFIX = '',
-        QT4_MOCDEFINES = '${_defines(QT4_MOCDEFPREFIX, CPPDEFINES, QT4_MOCDEFSUFFIX, __env__)}',
-        QT4_MOCCPPPATH = [],
-        QT4_MOCINCFLAGS = '$( ${_concat(QT4_MOCINCPREFIX, QT4_MOCCPPPATH, INCSUFFIX, __env__, RDirs)} $)',
-
-        # Commands for the qt4 support ...
-        QT4_UICCOM = '$QT4_UIC $QT4_UICFLAGS -o $TARGET $SOURCE',
-        QT4_LUPDATECOM = '$QT4_LUPDATE $QT4_LUPDATEFLAGS $SOURCES -ts $TARGET',
-        QT4_LRELEASECOM = '$QT4_LRELEASE $QT4_LRELEASEFLAGS -qm $TARGET $SOURCES',
-        
-        # Specialized variables for the Extended Automoc support
-        # (Strategy #1 for qtsolutions)
-        QT4_XMOCHPREFIX = 'moc_',
-        QT4_XMOCHSUFFIX = '.cpp',
-        QT4_XMOCCXXPREFIX = '',
-        QT4_XMOCCXXSUFFIX = '.moc',
-                
-        )
-
-    try:
-        env.AddMethod(Ts4, "Ts4")
-        env.AddMethod(Qm4, "Qm4")
-        env.AddMethod(Qrc4, "Qrc4")
-        env.AddMethod(ExplicitMoc4, "ExplicitMoc4")
-        env.AddMethod(ExplicitUic4, "ExplicitUic4")
-    except AttributeError:
-        # Looks like we use a pre-0.98 version of SCons...
-        from SCons.Script.SConscript import SConsEnvironment
-        SConsEnvironment.Ts4 = Ts4
-        SConsEnvironment.Qm4 = Qm4
-        SConsEnvironment.Qrc4 = Qrc4
-        SConsEnvironment.ExplicitMoc4 = ExplicitMoc4
-        SConsEnvironment.ExplicitUic4 = ExplicitUic4
-
-    # Interface builder
-    uic4builder = Builder(
-        action = SCons.Action.Action('$QT4_UICCOM', '$QT4_UICCOMSTR'),
-        src_suffix='$QT4_UISUFFIX',
-        suffix='$QT4_UICDECLSUFFIX',
-        prefix='$QT4_UICDECLPREFIX',
-        single_source = True
-        #TODO: Consider the uiscanner on new scons version
-        )
-    env['BUILDERS']['Uic4'] = uic4builder
-
-    # Metaobject builder
-    mocBld = Builder(action={}, prefix={}, suffix={})
-    for h in header_extensions:
-        act = SCons.Action.CommandGeneratorAction(__moc_generator_from_h, {})    
-        mocBld.add_action(h, act)
-        mocBld.prefix[h] = '$QT4_MOCHPREFIX'
-        mocBld.suffix[h] = '$QT4_MOCHSUFFIX'
-    for cxx in cxx_suffixes:
-        act = SCons.Action.CommandGeneratorAction(__moc_generator_from_cxx, {})    
-        mocBld.add_action(cxx, act)
-        mocBld.prefix[cxx] = '$QT4_MOCCXXPREFIX'
-        mocBld.suffix[cxx] = '$QT4_MOCCXXSUFFIX'
-    env['BUILDERS']['Moc4'] = mocBld
-
-    # Metaobject builder for the extended auto scan feature 
-    # (Strategy #1 for qtsolutions)
-    xMocBld = Builder(action={}, prefix={}, suffix={})
-    for h in header_extensions:
-        act = SCons.Action.CommandGeneratorAction(__mocx_generator_from_h, {})
-        xMocBld.add_action(h, act)
-        xMocBld.prefix[h] = '$QT4_XMOCHPREFIX'
-        xMocBld.suffix[h] = '$QT4_XMOCHSUFFIX'
-    for cxx in cxx_suffixes:
-        act = SCons.Action.CommandGeneratorAction(__mocx_generator_from_cxx, {})    
-        xMocBld.add_action(cxx, act)
-        xMocBld.prefix[cxx] = '$QT4_XMOCCXXPREFIX'
-        xMocBld.suffix[cxx] = '$QT4_XMOCCXXSUFFIX'
-    env['BUILDERS']['XMoc4'] = xMocBld
-
-    # Add the Qrc4 action to the CXX file builder (registers the
-    # *.qrc extension with the Environment)     
-    cfile_builder, cxxfile_builder = SCons.Tool.createCFileBuilders(env)
-    qrc_act = SCons.Action.CommandGeneratorAction(__qrc_generator, {})
-    cxxfile_builder.add_action('$QT4_QRCSUFFIX', qrc_act)    
-    cxxfile_builder.add_emitter('$QT4_QRCSUFFIX', __qrc_emitter)    
-
-    # We use the emitters of Program / StaticLibrary / SharedLibrary
-    # to scan for moc'able files
-    # We can't refer to the builders directly, we have to fetch them
-    # as Environment attributes because that sets them up to be called
-    # correctly later by our emitter.
-    env.AppendUnique(PROGEMITTER =[AutomocStatic],
-                     SHLIBEMITTER=[AutomocShared],
-                     LIBEMITTER  =[AutomocStatic],
-                    )
-
-    # TODO: Does dbusxml2cpp need an adapter
-    try:
-        env.AddMethod(enable_modules, "EnableQt4Modules")
-    except AttributeError:
-        # Looks like we use a pre-0.98 version of SCons...
-        from SCons.Script.SConscript import SConsEnvironment
-        SConsEnvironment.EnableQt4Modules = enable_modules
-
-def enable_modules(self, modules, debug=False, crosscompiling=False) :
-    import sys
-
-    validModules = [
-        'QtCore',
-        'QtGui',
-        'QtOpenGL',
-        'Qt3Support',
-        'QtAssistant', # deprecated
-        'QtAssistantClient',
-        'QtScript',
-        'QtDBus',
-        'QtSql',
-        'QtSvg',
-        # The next modules have not been tested yet so, please
-        # maybe they require additional work on non Linux platforms
-        'QtNetwork',
-        'QtTest',
-        'QtXml',
-        'QtXmlPatterns',
-        'QtUiTools',
-        'QtDesigner',
-        'QtDesignerComponents',
-        'QtWebKit',
-        'QtHelp',
-        'QtScript',
-        'QtScriptTools',
-        'QtMultimedia',
-        ]
-    pclessModules = [
-# in qt <= 4.3 designer and designerComponents are pcless, on qt4.4 they are not, so removed.    
-#        'QtDesigner',
-#        'QtDesignerComponents',
-    ]
-    staticModules = [
-        'QtUiTools',
-    ]
-    invalidModules=[]
-    for module in modules:
-        if module not in validModules :
-            invalidModules.append(module)
-    if invalidModules :
-        raise Exception("Modules %s are not Qt4 modules. Valid Qt4 modules are: %s"% (
-            str(invalidModules),str(validModules)))
-
-    moduleDefines = {
-        'QtScript'   : ['QT_SCRIPT_LIB'],
-        'QtSvg'      : ['QT_SVG_LIB'],
-        'Qt3Support' : ['QT_QT3SUPPORT_LIB','QT3_SUPPORT'],
-        'QtSql'      : ['QT_SQL_LIB'],
-        'QtXml'      : ['QT_XML_LIB'],
-        'QtOpenGL'   : ['QT_OPENGL_LIB'],
-        'QtGui'      : ['QT_GUI_LIB'],
-        'QtNetwork'  : ['QT_NETWORK_LIB'],
-        'QtCore'     : ['QT_CORE_LIB'],
-    }
-    for module in modules :
-        try : self.AppendUnique(CPPDEFINES=moduleDefines[module])
-        except: pass
-    debugSuffix = ''
-    if sys.platform in ["darwin", "linux2"] and not crosscompiling :
-        if debug : debugSuffix = '_debug'
-        for module in modules :
-            if module not in pclessModules : continue
-            self.AppendUnique(LIBS=[module+debugSuffix])
-            self.AppendUnique(LIBPATH=[os.path.join("$QT4DIR","lib")])
-            self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include","qt4")])
-            self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include","qt4",module)])
-        pcmodules = [module+debugSuffix for module in modules if module not in pclessModules ]
-        if 'QtDBus' in pcmodules:
-            self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include","qt4","QtDBus")])
-        if "QtAssistant" in pcmodules:
-            self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include","qt4","QtAssistant")])
-            pcmodules.remove("QtAssistant")
-            pcmodules.append("QtAssistantClient")
-        self.ParseConfig('pkg-config %s --libs --cflags'% ' '.join(pcmodules))
-        self["QT4_MOCCPPPATH"] = self["CPPPATH"]
-        return
-    if sys.platform == "win32" or crosscompiling :
-        if crosscompiling:
-            transformedQtdir = transformToWinePath(self['QT4DIR'])
-            self['QT4_MOC'] = "QT4DIR=%s %s"%( transformedQtdir, self['QT4_MOC'])
-        self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include")])
-        try: modules.remove("QtDBus")
-        except: pass
-        if debug : debugSuffix = 'd'
-        if "QtAssistant" in modules:
-            self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include","QtAssistant")])
-            modules.remove("QtAssistant")
-            modules.append("QtAssistantClient")
-        self.AppendUnique(LIBS=['qtmain'+debugSuffix])
-        self.AppendUnique(LIBS=[lib+debugSuffix+'4' for lib in modules if lib not in staticModules])
-        self.PrependUnique(LIBS=[lib+debugSuffix for lib in modules if lib in staticModules])
-        if 'QtOpenGL' in modules:
-            self.AppendUnique(LIBS=['opengl32'])
-        self.AppendUnique(CPPPATH=[ '$QT4DIR/include/'])
-        self.AppendUnique(CPPPATH=[ '$QT4DIR/include/'+module for module in modules])
-        if crosscompiling :
-            self["QT4_MOCCPPPATH"] = [
-                path.replace('$QT4DIR', transformedQtdir)
-                    for path in self['CPPPATH'] ]
-        else :
-            self["QT4_MOCCPPPATH"] = self["CPPPATH"]
-        self.AppendUnique(LIBPATH=[os.path.join('$QT4DIR','lib')])
-        return
-    """
-    if sys.platform=="darwin" :
-        # TODO: Test debug version on Mac
-        self.AppendUnique(LIBPATH=[os.path.join('$QT4DIR','lib')])
-        self.AppendUnique(LINKFLAGS="-F$QT4DIR/lib")
-        self.AppendUnique(LINKFLAGS="-L$QT4DIR/lib") #TODO clean!
-        if debug : debugSuffix = 'd'
-        for module in modules :
-#            self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include")])
-#            self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include",module)])
-# port qt4-mac:
-            self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include", "qt4")])
-            self.AppendUnique(CPPPATH=[os.path.join("$QT4DIR","include", "qt4", module)])
-            if module in staticModules :
-                self.AppendUnique(LIBS=[module+debugSuffix]) # TODO: Add the debug suffix
-                self.AppendUnique(LIBPATH=[os.path.join("$QT4DIR","lib")])
-            else :
-#                self.Append(LINKFLAGS=['-framework', module])
-# port qt4-mac:
-                self.Append(LIBS=module)
-        if 'QtOpenGL' in modules:
-            self.AppendUnique(LINKFLAGS="-F/System/Library/Frameworks")
-            self.Append(LINKFLAGS=['-framework', 'AGL']) #TODO ughly kludge to avoid quotes
-            self.Append(LINKFLAGS=['-framework', 'OpenGL'])
-        self["QT4_MOCCPPPATH"] = self["CPPPATH"]
-        return
-# This should work for mac but doesn't
-#    env.AppendUnique(FRAMEWORKPATH=[os.path.join(env['QT4DIR'],'lib')])
-#    env.AppendUnique(FRAMEWORKS=['QtCore','QtGui','QtOpenGL', 'AGL'])
-    """
-
-
-def exists(env):
-    return _detect(env)