← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-pkg/yade/git-trunk] Rev 3405: Merge github.com:yade/trunk into chaoUnsat

 

Merge authors:
  Alexander Eulitz [Eugen] (kubeu)
  Anton Gladky (gladky-anton)
  Anton Gladky (gladky-anton)
  Bruno Chareyre (bruno-chareyre)
  Bruno Chareyre (bruno-chareyre)...

------------------------------------------------------------
revno: 3405 [merge]
committer: Chao Yuan <chaoyuan2012@xxxxxxxxx>
timestamp: Mon 2014-02-17 19:00:12 +0100
message:
  Merge github.com:yade/trunk into chaoUnsat
  
  Conflicts:
  	lib/triangulation/def_types.h
removed:
  scripts/ppa/createtar.py
added:
  examples/adaptiveintegrator/
  examples/adaptiveintegrator/simple-scene-plot-NewtonIntegrator.py
  examples/adaptiveintegrator/simple-scene-plot-RungeKuttaCashKarp54.py
  examples/billiard.py
  examples/clumps/save-load-clumps.py
  examples/stl-gts/
  examples/stl-gts/README
  examples/stl-gts/cone.geo
  examples/stl-gts/convert2stl.sh
  examples/stl-gts/gts-stl.py
  examples/test/paraview-spheres-solid-section/
  examples/test/paraview-spheres-solid-section/export_text.py
  examples/test/paraview-spheres-solid-section/pv_section.py
  pkg/dem/FrictViscoPM.cpp
  pkg/dem/FrictViscoPM.hpp
  pkg/dem/GeneralIntegratorInsertionSortCollider.cpp
  pkg/dem/GeneralIntegratorInsertionSortCollider.hpp
  pkg/dem/Integrator.cpp
  pkg/dem/Integrator.hpp
  pkg/dem/RungeKuttaCashKarp54Integrator.cpp
  pkg/dem/RungeKuttaCashKarp54Integrator.hpp
  scripts/checks-and-tests/checks/checkViscElEng.py
  scripts/ppa/.dput.cf
  scripts/ppa/.mini-dinstall.conf
  scripts/ppa/buildppa.py
  scripts/ppa/ppa.config
modified:
  CMakeLists.txt
  ChangeLog
  INSTALL
  README.rst
  cMake/FindMetis.cmake
  core/ForceContainer.hpp
  core/InteractionContainer.cpp
  core/InteractionContainer.hpp
  core/main/main.py.in
  core/main/yade-batch.in
  doc/references.bib
  doc/sphinx/citing.rst
  doc/sphinx/formulation.rst
  doc/sphinx/installation.rst
  doc/sphinx/prog.rst
  doc/sphinx/publications.rst.in
  doc/sphinx/templates/index.html
  doc/sphinx/user.rst
  doc/yade-articles.bib
  doc/yade-conferences.bib
  examples/clumps/addToClump-example.py
  examples/concrete/triax.py
  examples/packs/packs.py
  examples/test/batch/sim.py
  examples/test/periodic-geom-compare.py
  examples/test/periodic-simple-shear.py
  examples/test/periodic-triax-settingHsize.py
  examples/test/periodic-triax.py
  examples/test/unv-read/unvRead.py
  examples/test/vtk-exporter/vtkExporter.py
  examples/tetra/oneTetra.py
  examples/timeStepperUsage.py
  examples/triax-tutorial/script-session1.py
  gui/qt4/GLViewer.cpp
  gui/qt4/GLViewer.hpp
  gui/qt4/GLViewerDisplay.cpp
  gui/qt4/GLViewerMouse.cpp
  gui/qt4/__init__.py
  lib/triangulation/FlowBoundingSphere.hpp
  lib/triangulation/FlowBoundingSphere.ipp
  lib/triangulation/FlowBoundingSphereLinSolv.ipp
  lib/triangulation/PeriodicFlow.cpp
  lib/triangulation/def_types.h
  pkg/common/Cylinder.cpp
  pkg/common/Dispatching.cpp
  pkg/common/Grid.cpp
  pkg/common/InsertionSortCollider.cpp
  pkg/common/InsertionSortCollider.hpp
  pkg/common/InteractionLoop.cpp
  pkg/common/OpenGLRenderer.cpp
  pkg/common/OpenGLRenderer.hpp
  pkg/common/SpatialQuickSortCollider.cpp
  pkg/common/Wall.cpp
  pkg/dem/CohFrictPhys.hpp
  pkg/dem/CohesiveFrictionalContactLaw.hpp
  pkg/dem/FlatGridCollider.cpp
  pkg/dem/FlowEngine.cpp
  pkg/dem/FlowEngine.hpp
  pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.cpp
  pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.cpp
  pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.hpp
  pkg/dem/JointedCohesiveFrictionalPM.cpp
  pkg/dem/JointedCohesiveFrictionalPM.hpp
  pkg/dem/L3Geom.hpp
  pkg/dem/NewtonIntegrator.cpp
  pkg/dem/NormalInelasticityLaw.cpp
  pkg/dem/Polyhedra.hpp
  pkg/dem/VTKRecorder.hpp
  pkg/dem/ViscoelasticCapillarPM.cpp
  pkg/dem/ViscoelasticPM.cpp
  pkg/dem/ViscoelasticPM.hpp
  py/_extraDocs.py
  py/_utils.cpp
  py/export.py
  py/geom.py
  py/pack/pack.py
  py/runtime.py
  py/tests/cohesive-chain.py
  py/utils.py
  py/ymport.py
  scripts/checks-and-tests/checks/DEM-PFV-check.py
  scripts/checks-and-tests/checks/checkWeight.py


--
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	2013-11-12 07:18:09 +0000
+++ CMakeLists.txt	2014-01-07 07:32:51 +0000
@@ -52,6 +52,12 @@
 ENDIF()
 
 #===========================================================
+
+IF ("${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" MATCHES ".*clang")
+  SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -ftemplate-depth-512")
+ENDIF()
+
+#===========================================================
 ADD_DEFINITIONS(" -DYADE_PTR_CAST=static_pointer_cast -DYADE_CAST=static_cast ")
 IF (CMAKE_CXX_FLAGS)
   #If flags are set, add only neccessary flags
@@ -259,7 +265,7 @@
     MESSAGE(STATUS "Found Metis")
     SET(CONFIGURED_FEATS "${CONFIGURED_FEATS} LinSolv")
   ELSE(CHOLMOD_FOUND AND OPENBLAS_FOUND AND METIS_FOUND)
-    MESSAGE(STATUS "CHOLMOD NOT found, LINSOLV disabled")
+    MESSAGE(STATUS "Missing dependency for LINSOLV, disabled")
     SET(DISABLED_FEATS "${DISABLED_FEATS} LinSolv")
     SET(ENABLE_LINSOLV OFF)
   ENDIF(CHOLMOD_FOUND AND OPENBLAS_FOUND AND METIS_FOUND)

=== modified file 'ChangeLog'
--- ChangeLog	2013-10-28 18:49:33 +0000
+++ ChangeLog	2014-01-10 20:30:37 +0000
@@ -1,6 +1,105 @@
 ==================================================
+yade-1.07.0
+Fri, 10 Jan 2014 21:23:33 +0100
+
+Anton Gladky (37):
+      Remove RELEASE file.
+      Add -ftrack-macro-expansion=0, if gcc>=4.8
+      Provide VTK6-support.
+      Use ADD_DEFINITIONS instead of adding those directly in CXX_FLAGS.
+      Remove information about yade-stable from Readme.
+      Add BicyclePedalEngine as a new kinematic motion.
+      Add -save-temps if GCC-4.8 is used.
+      Split Grid into Grid and Grid_GUI.
+      Add information about missing packages in documentation and external PPA. Closes: LP:1250928
+      Add notice about using libqglviewer-qt4-dev instead of libqglviewer-dev on older Ubuntu versions.
+      Add script to create PPA-packages. (Not finished)
+      Use othermirror for some ubuntu versions.
+      Add stl-gts example.
+      Add qt.View() to clumps-example.
+      Add one more check-script to check the functionality of ViscoElastic PM.
+      Consider massMultiply-parameter, calculating parameters in     ViscoElasticPM.
+      Add functions to save and load clumps.
+      Set the higher pripority in sys.path to self-compiled modules. Closes LP:1254708
+      Fix volume calculation. Closes LP:1261415
+      Set the higher pripority in sys.path to self-compiled modules in     yade-batch.
+      Update scripts for PPA.
+      Add configuration files, needed for PPA.
+      Minor update of PPA scripts.
+      Update information about yadedaily prebuilt packages.
+      Add support for qglviewer>=2.5.0.
+      Open GUI in packs/packs.py after 1 step to show all elements.
+      Raise warning, if no spheres are produced by regular* commands.
+      Update information about daily-packages.
+      Set one more paramter -ftemplate-depth-512 for clang
+      Prevent attraction forces in ViscPM due to viscosity
+      Add some more steps to checkWeight-script.
+      Minor formatting in references.
+      Remove cout accidentally added in a prev. commit.
+      Minor change of setFromTwoVectors in utils.py.
+      Rename createtar.py to buildppa.py.
+      Minor fix in docs.
+      Add RELEASE-file.
+
+Bruno Chareyre (17):
+      a function to increase the size of a single sphere (~>Thomas swelling)
+      easier manipulation of state files in TesselationWrapper
+      restore the python wrapping of utils.growParticles() as it was before fb02a74 (changed by mistake, sorry Christian)
+      give unique identifiers to trangulation's cells
+      FlowEngine::nCells retruns the number of finite cells; FlowEngine::getVertices returns the vertices of a cell defined by its id
+      make cmake output more consistent when missing dependency for LinSolv
+      Fix the behavior of FlowEngine.updateTriangulation=True
+      FlowEngine: increment a counter correctly
+      small changes in the installation section regarding suitesparse and related libs
+      installation.rst: smallfix in indentation
+      remove a not necessary sorting in FlowEngine, as it triggers a critical bug in the STL (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58800)
+      correct target values of the DEM-PFV checktest
+      Fix paths to online and packaged documentation (fix url error with GUI's hyperlinks)
+      DEM Background chapter: a note on the semantic strain vs. displacement for contact kinematics
+      Merge branch 'master' of github.com:yade/trunk
+      fix undefined "key" in triax-tutorial/script-session1.py
+      +1 published paper
+
+Christian Jakob (1):
+      small fix in an example script tetra/oneTetra.py
+
+Francois (3):
+      Fix missing REGISTER_CLASS_INDEX(...) into ViscElPhys. This macro is essential for a right law dispatch !
+      Corrected a minor mistake in code comments : k=2*r*E
+      Allow the contact between (coh)frictMat and viscElMat as frictPhys. Almost everything was done by inheritance, just had to convert stiffnesses to modulus and modulus to stiffnesses to ensure material compatibility.     Note that for the moment the timeStepper cannot handle this kind of simulations -> will be fixed soon.
+
+Jan Stransky (4):
+      Modified error message if not yade.runtime.hasDisplay (bug #1241817)
+      fixed SyntaxError from previous commit
+      uncomment and modify utils.forcesOnCoordPlane function
+      corrected mistake in examples/test/triax.py
+
+Jerome Duriez (15):
+      - Introducing (uncommenting in fact) tens/shearBreakRel variables in JCFpmState : relative part of broken interactions per body (instead of absolute number).     - Few changes in some doc of JCFpm variables.
+      Quite important changes in JCFpm code
+      Modifying JCFpm example scripts so that they still work after previous commit
+      Re-put some commented lines, after discussion of this thread (https://lists.launchpad.net/yade-dev/msg10185.html), thanks Anton. The comments solution is (at the moment ?) finally still used to avoid putting a new variable in VTKRecorder..
+      A script example for JCFpm : two rock parts with one joint in the middle, like in laboratory experiments
+      Some forgotten corrections in some example scripts, so that they still work after changes of today in JCFpm
+      Some corrections in the JCFpm doc (hyperlinks...)
+      (Hopefully) Fixing some rst links in DEM Background doc
+      Some changes in the doc of getStress() function, to be consistent with the source code (https://answers.launchpad.net/yade/+question/239919)
+      Merge branch 'master' of github.com:yade/trunk
+      Idem as previous commit
+      Restoring the 2d version of growParticle previously erased by mistake..
+      Some hyperlinks in JCFpm doc corrected
+      Typos and hyperlinks corrected in Peri3dController doc
+      Correction of a link in TesselationWrapper() doc
+
+Klaus Thoeni (1):
+      add CGAL link and delete libgmp3 from install list
+
+Raphael Maurin (1):
+      Change in the calculation of the normal and tangential stiffness and damping. The change affects only the behavior     when one of the two parameters is zero, e.g. for two particles with different stiffness k1 and k2, the contact     stiffness will always be k = k1*k2/(k1+k2). Before it gave the same except when k2 = 0 (respectively k1 = 0), where it     gave k = k1 (resp. k=k2). This is done to ensure continuity in the behavior when one of the two parameter tend     to zero.     Add a function contactParameterCalculation in Ip2_ViscElMat_ViscElMat_ViscElPhys to avoid code duplication.
+
+==================================================
 yade-1.05.0
-Mon Oct 28 19:49:48 2013 +0200
+Mon, Oct 28 19:49:48 2013 +0200
 
 Anton Gladky (19):
       Add system-component of boost to be linked.
@@ -76,7 +175,7 @@
 
 ==================================================
 yade-1.00.0
-Sun Sep 29 23:10:48 2013 +0200
+Sun, Sep 29 23:10:48 2013 +0200
 
 Anton Gladky (64):
       Remove release file.
@@ -302,7 +401,7 @@
 
 ==================================================
 yade-0.97.0
-Sun May 12 14:48:29 2013 +0200
+Sun, May 12 14:48:29 2013 +0200
 
 Anton Gladky (42):
       Remove release-file.
@@ -447,7 +546,7 @@
 
 ==================================================
 yade-0.95.0
-Tue Mar 5 20:36:40 2013 +0100
+Tue, Mar 5 20:36:40 2013 +0100
 
 Anton Gladky (41):
       Remove RELEASE file.
@@ -640,7 +739,7 @@
 
 ==================================================
 yade-0.90.0
-Sat Oct 13 15:16:55 2012 +0200
+Sat, Oct 13 15:16:55 2012 +0200
 
 Anton Gladky (142):
       Remove RELEASE file.
@@ -912,7 +1011,7 @@
 
 ==================================================
 yade-0.80.0
-Wed May 2 21:05:12 2012 +0200
+Wed, May 2 21:05:12 2012 +0200
 
 Anton Gladky (81):
       Add forgotten format to ymport.textExt
@@ -1123,7 +1222,7 @@
 
 ==================================================
 yade-0.70.0
-Sun Oct 23 16:49:34 2011 +0200
+Sun, Oct 23 16:49:34 2011 +0200
 
 Anton Gladky (129):
       1. Prediction of simulation finish time is added to HTTP-batch server.
@@ -1591,7 +1690,7 @@
 
 ==================================================
 yade-0.60.0
-Sun Nov 7 09:55:43 2010 +0100
+Sun, Nov 7 09:55:43 2010 +0100
 
 Anton Gladky (54):
       1. utils.facetCylinder and utils.facetBox orientations are changed according to https://lists.launchpad.net/yade-dev/msg04886.html
@@ -1864,7 +1963,7 @@
 
 ==================================================
 yade-0.50.0
-Wed Jun 9 08:30:02 2010 +0200
+Wed, Jun 9 08:30:02 2010 +0200
 
 Anton Gladky (77):
       Added an example of VTK-recorder using. Thanks Sergei Doroffenko aka Sega
@@ -2464,7 +2563,7 @@
 
 ==================================================
 yade-0.20.2
-Sat Sep 19 21:41:52 2009 +0200
+Sat, Sep 19 21:41:52 2009 +0200
 
 Anton Gladky (34):
       1. This is my first test commit     2. Added some initial files for mining rocks classes simulation
@@ -2999,7 +3098,7 @@
 
 ==================================================
 yade-0.20.0
-Sat Sep 19 21:41:52 2009 +0200
+Sat, Sep 19 21:41:52 2009 +0200
 
 Anton Gladky (33):
       1. This is my first test commit     2. Added some initial files for mining rocks classes simulation
@@ -3452,7 +3551,7 @@
 
 ==================================================
 yade-0.12.1
-Sat Nov 22 22:48:27 2008 +0000
+Sat, Nov 22 22:48:27 2008 +0000
 
 Bruno Chareyre (6):
       A wrong comment on contact laws in PFC3D is removed.
@@ -3551,7 +3650,7 @@
 
 ==================================================
 yade-0.12.0
-Wed Aug 20 14:37:02 2008 +0000
+Wed, Aug 20 14:37:02 2008 +0000
 
 Janek Kozicki (8):
       testing if SVN commit messages can go to launchpad
@@ -3592,7 +3691,7 @@
 
 ==================================================
 yade-0.12.0rc1
-Sun Jul 27 10:52:50 2008 +0000
+Sun, Jul 27 10:52:50 2008 +0000
 
 Bruno Chareyre (69):
       Modifications in the equations of "non-viscous" damping. The equations     are now as defined by Cundall.

=== modified file 'INSTALL'
--- INSTALL	2011-10-23 14:49:34 +0000
+++ INSTALL	2014-01-13 17:49:26 +0000
@@ -1,1 +1,9 @@
+Installation instructions are updating regularly. 
+The most actual instruction can be found on the 
+website:
+
 http://www.yade-dem.org/doc/installation.html
+
+which is generated from the following file:
+
+doc/sphinx/installation.rst

=== modified file 'README.rst'
--- README.rst	2013-11-10 21:23:19 +0000
+++ README.rst	2014-01-06 14:13:01 +0000
@@ -16,9 +16,9 @@
  
 **Downloads:**
 
-- Packages for Ubuntu:
+- Packages for Ubuntu and Debian:
   
-  - Daily-builds: https://launchpad.net/~yade-pkg/+archive/snapshots
+  - https://yade-dem.org/doc/installation.html#packages
   - External packages: https://launchpad.net/~yade-users/+archive/external
 
 - Tarballs of different versions: 

=== modified file 'cMake/FindMetis.cmake'
--- cMake/FindMetis.cmake	2013-08-30 13:49:57 +0000
+++ cMake/FindMetis.cmake	2014-02-16 16:42:06 +0000
@@ -6,7 +6,7 @@
 #  METIS_FOUND, If false, do not try to use GL2PS.
 
 FIND_PATH(METIS_INCLUDE_DIR metis.h PATHS /usr/include/metis)
-FIND_LIBRARY(METIS_LIBRARY NAMES metis PATHS /usr/lib)
+FIND_LIBRARY(METIS_LIBRARY NAMES metis parmetis PATHS /usr/lib)
 
 # handle the QUIETLY and REQUIRED arguments and set LOKI_FOUND to TRUE if
 # all listed variables are TRUE

=== modified file 'core/ForceContainer.hpp'
--- core/ForceContainer.hpp	2013-09-24 06:14:29 +0000
+++ core/ForceContainer.hpp	2014-01-20 16:13:36 +0000
@@ -234,7 +234,7 @@
 		const Vector3r& getPermForce(Body::id_t id) { ensureSize(id); return _permForce[id]; }
 		const Vector3r& getPermTorque(Body::id_t id) { ensureSize(id); return _permTorque[id]; }
 		// single getters do the same as globally synced ones in the non-parallel flavor
-		const Vector3r& getForceSingle (Body::id_t id){ 
+		const Vector3r getForceSingle (Body::id_t id){ 
 			ensureSize(id); 
 			if (permForceUsed) {
 				return _force [id] + _permForce[id];
@@ -242,7 +242,7 @@
 				return _force [id];
 			}
 		}
-		const Vector3r& getTorqueSingle(Body::id_t id){ 
+		const Vector3r getTorqueSingle(Body::id_t id){ 
 			ensureSize(id); 
 			if (permForceUsed) {
 				return _torque[id] + _permTorque[id];

=== modified file 'core/InteractionContainer.cpp'
--- core/InteractionContainer.cpp	2013-03-06 17:30:45 +0000
+++ core/InteractionContainer.cpp	2014-02-03 11:21:42 +0000
@@ -46,7 +46,6 @@
 		if (b) b->intrs.clear(); // delete interactions from bodies
 	}
 	linIntrs.clear(); // clear the linear container
-	pendingErase.clear();
 	currSize=0;
 	dirty=true;
 }
@@ -116,14 +115,9 @@
 }
 
 
-void InteractionContainer::requestErase(Body::id_t id1, Body::id_t id2, bool force){
+void InteractionContainer::requestErase(Body::id_t id1, Body::id_t id2){
 	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);
-	#else
-		pendingErase.push_back(v);
-	#endif
+	I->reset();
 }
 
 void InteractionContainer::requestErase(const shared_ptr<Interaction>& I){
@@ -134,41 +128,8 @@
 	I->reset();
 }
 
-void InteractionContainer::clearPendingErase(){
-	#ifdef YADE_OPENMP
-		FOREACH(list<IdsForce>& pendingErase, threadsPendingErase){
-			pendingErase.clear();
-		}
-	#else
-		pendingErase.clear();
-	#endif
-}
-
-int InteractionContainer::unconditionalErasePending(){
-	int ret=0;
-	#ifdef YADE_OPENMP
-		// shadow this->pendingErase by the local variable, to share code
-		FOREACH(list<IdsForce>& pendingErase, threadsPendingErase){
-	#endif
-			if(!pendingErase.empty()){
-				FOREACH(const IdsForce& p, pendingErase){ ret++; erase(p.id1,p.id2); }
-				pendingErase.clear();
-			}
-	#ifdef YADE_OPENMP
-		}
-	#endif
-	return ret;
-}
-
 void InteractionContainer::eraseNonReal(){
-	typedef pair<int,int> Ids;
-	std::list<Ids> ids;
-	FOREACH(const shared_ptr<Interaction>& i, *this){
-		if(!i->isReal()) ids.push_back(Ids(i->getId1(),i->getId2()));
-	}
-	FOREACH(const Ids& id, ids){
-		this->erase(id.first,id.second);
-	}
+	FOREACH(const shared_ptr<Interaction>& i, *this) if(!i->isReal()) this->erase(i->getId1(),i->getId2());
 }
 
 // compare interaction based on their first id

=== modified file 'core/InteractionContainer.hpp'
--- core/InteractionContainer.hpp	2012-01-23 14:43:54 +0000
+++ core/InteractionContainer.hpp	2014-02-03 11:21:42 +0000
@@ -65,9 +65,9 @@
 		// required by the class factory... :-|
 		InteractionContainer(): currSize(0),dirty(false),serializeSorted(false),iterColliderLastRun(-1){
 			bodies=NULL;
-			#ifdef YADE_OPENMP
-				threadsPendingErase.resize(omp_get_max_threads());
-			#endif
+// 			#ifdef YADE_OPENMP
+// 				threadsPendingErase.resize(omp_get_max_threads());
+// 			#endif
 		}
 		void clear();
 		// iterators
@@ -101,74 +101,23 @@
 		bool serializeSorted;
 		// iteration number when the collider was last run; set by the collider, if it wants interactions that were not encoutered in that step to be deleted by InteractionLoop (such as SpatialQuickSortCollider). Other colliders (such as InsertionSortCollider) set it it -1, which is the default
 		long iterColliderLastRun;
-		//! Ask for erasing the interaction given (from the constitutive law); this resets the interaction (to the initial=potential state) and collider should traverse pendingErase to decide whether to delete the interaction completely or keep it potential
-		void requestErase(Body::id_t id1, Body::id_t id2, bool force=false);
+		//! Ask for erasing the interaction given (from the constitutive law); this resets the interaction (to the initial=potential state) and collider should traverse potential interactions to decide whether to delete them completely or keep them potential
+		void requestErase(Body::id_t id1, Body::id_t id2);
 		void requestErase(const shared_ptr<Interaction>& I);
 		void requestErase(Interaction* I);
-		/*! List of pairs of interactions that will be (maybe) erased by the collider; if force==true, they will be deleted unconditionally.
-			
-			If accessed from within a parallel section, pendingEraseMutex must be locked (this is done inside requestErase for you).
-
-			If there is, at one point, a multi-threaded collider, pendingEraseMutex should be moved to the public part and used from there as well.
-		*/
-		struct IdsForce{ Body::id_t id1; Body::id_t id2; bool force; };
-		#ifdef YADE_OPENMP
-			vector<list<IdsForce> > threadsPendingErase;
-		#endif
-		list<IdsForce> pendingErase;
-		/*! Erase all pending interactions unconditionally.
-
-			This should be called only in rare cases that collider is not used but still interactions should be erased.
-			Otherwise collider should decide on a case-by-case basis, which interaction to erase for good and which to keep in the potential state
-			(without geom and phys).
-
-			This function doesn't lock pendingEraseMutex, as it is (supposedly) called from no-parallel sections only once per iteration
-		*/
-		int unconditionalErasePending();
-
-		/*! Clear the list of interaction pending erase: all interactions queued for considering erasing them
-		will be dropped; useful for colliders that handle that by themselves, without needing the hint;
-		with openMP, it would not be enough to call pendingErase->clear(), this helper function 
-		does it for all threads. Use this only if you understand this explanation. */
-		void clearPendingErase();
-
-		/*! Traverse all pending interactions and erase them if the (T*)->shouldBeErased(id1,id2) return true
-			and keep it if it return false; finally, pendingErase will be clear()'ed.
-
-			Class using this interface (which is presumably a collider) must define the 
-					
-				bool shouldBeErased(Body::id_t, Body::id_t) const
-
-			method which will be called for every interaction.
-
-			Returns number of interactions, have they been erased or not (this is useful to check if there were some erased, after traversing those)
-		*/
-		template<class T> int erasePending(const T& t, Scene* rb){
-			int ret=0;
-			#ifdef YADE_OPENMP
-				// shadow the this->pendingErase by the local variable, to share the code
-				FOREACH(list<IdsForce>& pendingErase, threadsPendingErase){
-			#endif
-					FOREACH(const IdsForce& p, pendingErase){
-						ret++;
-						if(p.force || t.shouldBeErased(p.id1,p.id2,rb)) erase(p.id1,p.id2);
-					}
-					pendingErase.clear();
-			#ifdef YADE_OPENMP
-				}
-			#endif
-			return ret;
-		}
+
 		/*! Traverse all interactions and erase them if they are not real and the (T*)->shouldBeErased(id1,id2) return true, or if body(id1) has been deleted
 			Class using this interface (which is presumably a collider) must define the
 				bool shouldBeErased(Body::id_t, Body::id_t) const
 		*/
-		template<class T> void conditionalyEraseNonReal(const T& t, Scene* rb){
+		template<class T> size_t conditionalyEraseNonReal(const T& t, Scene* rb){
 			// beware iterators here, since erase is invalidating them. We need to iterate carefully, and keep in mind that erasing one interaction is moving the last one to the current position.
+			size_t initSize=currSize;
 		 	for (size_t linPos=0; linPos<currSize;){
 				const shared_ptr<Interaction>& i=linIntrs[linPos];
 				if(!i->isReal() && t.shouldBeErased(i->getId1(),i->getId2(),rb)) erase(i->getId1(),i->getId2(),linPos);
 				else linPos++;}
+			return initSize-currSize;
 		}
 
 	// we must call Scene's ctor (and from Scene::postLoad), since we depend on the existing BodyContainer at that point.

=== modified file 'core/main/main.py.in'
--- core/main/main.py.in	2013-09-10 14:53:54 +0000
+++ core/main/main.py.in	2014-02-03 16:10:20 +0000
@@ -8,6 +8,13 @@
 except ImportError:
 	import io
 
+# Add search path for yade Python-modules
+# It allows to use both Yade-versions (packaged and self-compiled one).
+# See LP:1254708 for more details
+# https://bugs.launchpad.net/yade/+bug/1254708
+
+sys.path.insert(1,'${runtimePREFIX}/${LIBRARY_OUTPUT_PATH}/yade${SUFFIX}/py')
+
 # 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
@@ -21,9 +28,6 @@
 if not (os.path.exists(libDir+'/py/yade/__init__.py')):
 	raise RuntimeError('Libraries are not found! ('+libDir+'/py/yade/__init__.py, /py/yade/__init__.py)')
 
-
-
-
 # handle command-line options first
 try:
 	import argparse
@@ -100,7 +104,7 @@
 if not 'openmp' in features and (opts.cores or (opts.threads and opts.threads>1)):
 	print 'WARNING: compiled without OpenMP, -j/--threads/--cores have no effect.'
 
-# OpenMP env variables must be se before loading yade libs ("import yade" below)
+# OpenMP env variables must be set before loading yade libs ("import yade" below)
 # changes have no effeect after libgomp initializes
 if opts.cores:
 	if opts.threads: print 'WARNING: --threads ignored, since --cores specified.'
@@ -216,7 +220,10 @@
 		ipshell=InteractiveShellEmbed()
 		ipshell()
 	elif yade.runtime.ipython_version>=12:
-		from IPython.frontend.terminal.embed import InteractiveShellEmbed
+		if yade.runtime.ipython_version>=100:
+			from IPython.terminal.embed import InteractiveShellEmbed
+		else:
+			from IPython.frontend.terminal.embed import InteractiveShellEmbed
 		from IPython.config.loader import Config
 		cfg = Config()
 		prompt_config = cfg.PromptManager

=== modified file 'core/main/yade-batch.in'
--- core/main/yade-batch.in	2013-05-24 16:48:19 +0000
+++ core/main/yade-batch.in	2013-12-20 15:10:54 +0000
@@ -6,6 +6,13 @@
 
 import os, sys, thread, time, logging, pipes, socket, xmlrpclib, re, shutil, random
 
+# Add search path for yade Python-modules
+# It allows to use both Yade-versions (packaged and self-compiled one).
+# See LP:1254708 for more details
+# https://bugs.launchpad.net/yade/+bug/1254708
+
+sys.path.insert(1,'${runtimePREFIX}/${LIBRARY_OUTPUT_PATH}/yade${SUFFIX}/py')
+
 #socket.setdefaulttimeout(10) 
 
 ## replaced by scons automatically

=== modified file 'doc/references.bib'
--- doc/references.bib	2013-10-04 12:35:58 +0000
+++ doc/references.bib	2014-01-29 16:26:55 +0000
@@ -621,12 +621,49 @@
 }
 
 @article{Ivars2011,
-title = "The synthetic rock mass approach for jointed rock mass modelling ",
-journal = "International Journal of Rock Mechanics and Mining Sciences ",
-volume = "48",
-number = "2",
-pages = "219 - 244",
-year = "2011",
-doi = "10.1016/j.ijrmms.2010.11.014",
-author = "Diego Mas Ivars and Matthew E. Pierce and Caroline Darcel and Juan Reyes-Montes and David O. Potyondy and R. Paul Young and Peter A. Cundall"
+	title = "The synthetic rock mass approach for jointed rock mass modelling ",
+	journal = "International Journal of Rock Mechanics and Mining Sciences ",
+	volume = "48",
+	number = "2",
+	pages = "219 - 244",
+	year = "2011",
+	doi = "10.1016/j.ijrmms.2010.11.014",
+	author = "Diego Mas Ivars and Matthew E. Pierce and Caroline Darcel and Juan Reyes-Montes and David O. Potyondy and R. Paul Young and Peter A. Cundall"
+}
+
+@book{Radjai2011,
+	title={Discrete-Element Modeling of Granular Materials},
+	author={Radjai, F. and Dubois, F.},
+	isbn={9781848212602},
+	lccn={2010051720},
+	url={http://books.google.com/books?id=w2ijcQAACAAJ},
+	year={2011},
+	publisher={John Wiley \& Sons}
+}
+
+@article{Schwager2007,
+	year={2007},
+	issn={1434-5021},
+	journal={Granular Matter},
+	volume={9},
+	number={6},
+	doi={10.1007/s10035-007-0065-z},
+	title={Coefficient of restitution and linear–dashpot model revisited},
+	url={http://dx.doi.org/10.1007/s10035-007-0065-z},
+	publisher={Springer-Verlag},
+	keywords={Particle collisions; Coefficient of restitution},
+	author={Schwager, Thomas and Pöschel, Thorsten},
+	pages={465-469},
+	language={English}
+}
+
+@article{Lambert2008,
+	title={Comparison between two capillary forces models},
+	author={Lambert, Pierre and Chau, Alexandre and Delchambre, Alain and R{\'e}gnier, St{\'e}phane},
+	journal={Langmuir},
+	volume={24},
+	number={7},
+	pages={3157--3163},
+	year={2008},
+	publisher={ACS Publications}
 }

=== modified file 'doc/sphinx/citing.rst'
--- doc/sphinx/citing.rst	2012-09-08 01:19:45 +0000
+++ doc/sphinx/citing.rst	2014-01-13 17:49:25 +0000
@@ -16,7 +16,7 @@
 
 Citing chapters of Yade Documentation
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The first edition of Yade documentation is seen as a collection with the three volumes (or "chapters") listed below, also provided as `bibtex entries <http://bazaar.launchpad.net/~yade-dev/yade/trunk/view/head:/doc/citing_yade.bib>`_. Please cite the chapter that is the most relevant in your case. For instance, a paper using one of the documented contact laws will cite the reference documentation [yade:reference]_; if programing concepts are discussed, Yade's manual [yade:manual]_ will be cited; the theoretical background [yade:background]_ can be used as the refence for contact detection, time-step determination, or periodic boundary conditions.
+The first edition of Yade documentation is seen as a collection with the three volumes (or "chapters") listed below, also provided as `bibtex entries <https://github.com/yade/trunk/blob/master/doc/citing_yade.bib>`_. Please cite the chapter that is the most relevant in your case. For instance, a paper using one of the documented contact laws will cite the reference documentation [yade:reference]_; if programing concepts are discussed, Yade's manual [yade:manual]_ will be cited; the theoretical background [yade:background]_ can be used as the refence for contact detection, time-step determination, or periodic boundary conditions.
 
 * The reference documentation includes details on equations and algorithms found at the highest levels of Yade (contact laws, boundary conditions controllers, pre- and post-processing modules,...) `(pdf version) <https://yade-dem.org/w/images/9/98/YadeRefDoc.pdf>`__:
 	V. Šmilauer, E. Catalano, B. Chareyre, S. Dorofeenko, J. Duriez, A. Gladky, J. Kozicki, C. Modenese, L. Scholtès, L. Sibille, J. Stránský, and K. Thoeni, “Yade Reference Documentation,” in Yade Documentation (V. Šmilauer, ed.), The Yade Project, 1st ed., 2010. http://yade-dem.org/doc/.

=== modified file 'doc/sphinx/formulation.rst'
--- doc/sphinx/formulation.rst	2013-11-06 15:53:55 +0000
+++ doc/sphinx/formulation.rst	2013-12-04 22:12:56 +0000
@@ -16,6 +16,8 @@
 
 This simplified description serves only to give meaning to the ordering of sections within this chapter. A more detailed description of this *simulation loop* is given later.
 
+In this chapter we refer to kinematic variables of the contacts as \`\`strains``, although at this scale it is also common to speak of \`\`displacements``. Which semantic is more appropriate depends on the conceptual model one is starting from, and therefore it cannot be decided independently of specific problems. The reader familiar with displacements can mentaly replace normal strain and shear strain by normal displacement and shear displacement, respectively, without altering the meaning of what follows.
+
 Collision detection
 =====================
 

=== modified file 'doc/sphinx/installation.rst'
--- doc/sphinx/installation.rst	2013-11-14 09:27:47 +0000
+++ doc/sphinx/installation.rst	2014-02-03 16:11:58 +0000
@@ -10,24 +10,38 @@
 Packages
 ----------
 
-Packages from Launchpad PPA service (package personal archive) are 
-provided for all currently supported Ubuntu versions for 
-`daily <https://launchpad.net/~yade-pkg/+archive/snapshots>`_ releases.
-``yade-daily`` is a automatically daily (if there were some commtis during
-the previous days) generated package, which includes all the newly added 
-features. To install version from PPA, run the following:
-
-* For latest builds from trunk::
-
-	sudo add-apt-repository ppa:yade-pkg/snapshots    # for latest daily (mostly) releases 
-	sudo apt-get update
-	sudo apt-get install yade-daily
-
-After you added snapshot PPA, you will get automatically the updates of the package, 
-when they arrive the PPA.
-
-More detailed instructions are available at the corresponding pages of 
-ppa`s (links above).
+Pre-built packages are provided for all currently supported Debian and Ubuntu 
+versions of distributions and available on `yade-dem.org <http://yade-dem.org/packages/>`_  
+server. 
+
+These are ``daily`` versions of packages and are updating regularly and include 
+all the newly added features.
+
+To install daily-version one needs to add this repository to your 
+/etc/apt/sources.list, add a PGP-key AA915EEB as a trusted and install yadedaily ::
+
+	sudo bash -c 'echo "deb http://www.yade-dem.org/packages/ precise/" >> /etc/apt/sources.list'
+	wget -O - http://www.yade-dem.org/packages/yadedev_pub.gpg | sudo apt-key add -
+	sudo apt-get install yadedaily
+
+If you have another distribution, not Ubuntu Precise, be sure to use the
+correct name in the first line (for instance, jessie, trusty or wheezy).
+
+After that you can normally start Yade using "yadedaily" or "yadedaily-batch" command.
+
+Git-repository for packaging stuff is available on `GitHub <https://github.com/yade/yadedaily/>`_. 
+Each branch corresponds to one distribution e.g. precise, jessie etc.
+The scripts for building all of this stuff is `here <https://github.com/yade/trunk/tree/master/scripts/ppa>`_. 
+It uses pbuilder to build packages, so all packages are building in a clean environment.
+
+If you do not need yadedaily-package any more, just remove the
+corresponding line in /etc/apt/sources.list and the package itself::
+
+	sudo apt-get remove yadedaily
+
+To remove our key from keyring, execute the following command::
+
+	sudo apt-key remove AA915EEB
 
 Since 2011 all Ubuntu versions (starting from 11.10, Oneiric) and Debian (starting from Wheezy) 
 are having already Yade in their main repositories. There are only stable releases are placed.
@@ -35,10 +49,14 @@
 
 	sudo apt-get install yade
 
-To check, what version of Yade is in specific Distribution, check the links
+To check, what version of Yade is in specific distribution, visit the links
 for `Ubuntu <https://launchpad.net/ubuntu/+source/yade>`_ and 
-`Debian <http://packages.qa.debian.org/y/yade.html>`_.
+`Debian <http://packages.qa.debian.org/y/yade.html>`_. 
+`Debian-Backports <http://backports.debian.org/Instructions>`_ 
+repository is updating regularly to bring the newest Yade to a users of stable 
+Debians.
 
+Daily and stable Yade versions can coexist without any conflicts.
 
 Source code
 ------------
@@ -82,7 +100,8 @@
 Prerequisites
 ^^^^^^^^^^^^^
 
-Yade relies on a number of external software to run; its installation is checked before the compilation starts. 
+Yade relies on a number of external software to run; they are checked before the compilation starts.
+Some of them are only optional. The last ones are only relevant for using the fluid coupling module (:yref:`FlowEngine`).
 
 * `cmake <http://www.cmake.org/>`_ build system
 * `gcc <http://www.gcc.gnu.org>`_ compiler (g++); other compilers will not work; you need g++>=4.2 for openMP support
@@ -98,13 +117,24 @@
 * `Loki <http://loki-lib.sf.net>`_ library
 * `VTK <http://www.vtk.org/>`_ library (optional but recommended)
 * `CGAL <http://www.cgal.org/>`_ library (optional)
+* `SuiteSparse <http://www.cise.ufl.edu/research/sparse/SuiteSparse/>`_ sparse algebra library (fluid coupling, optional, requires eigen>=3.1)
+* `OpenBLAS <http://www.openblas.net/>`_ optimized and parallelized alternative to the standard blas+lapack (fluid coupling, optional)
+* `Metis <http://glaros.dtc.umn.edu/gkhome/metis/metis/overview/>`_ matrix preconditioning (fluid coupling, optional)
 
-Most of the list above is very likely already packaged for your distribution. 
+Most of the list above is very likely already packaged for your distribution. In case you are confronted
+with some errors concerning not available packages (e.g. Package libmetis-dev is not available) it may be necessary 
+to add yade external ppa from https://launchpad.net/~yade-users/+archive/external::
+	sudo add-apt-repository ppa:yade-users/external 
+	sudo apt-get update 
 The following commands have to be executed in command line of corresponding 
 distributions. Just copy&paste to the terminal. To perform commands you 
 should have root privileges
 
-	* **Ubuntu**, **Debian** and their derivatives::
+.. warning:: If you have Ubuntu 12.10 or older, you need to install libqglviewer-qt4-dev
+ package instead of libqglviewer-dev.
+
+ 
+* **Ubuntu**, **Debian** and their derivatives::
 
 		sudo apt-get install cmake git freeglut3-dev libloki-dev \
 		libboost-all-dev fakeroot dpkg-dev build-essential g++ \
@@ -112,29 +142,36 @@
 		libgts-dev python-pygraphviz libvtk5-dev python-scientific libeigen3-dev \
 		python-xlib python-qt4 pyqt4-dev-tools gtk2-engines-pixbuf python-argparse \
 		libqglviewer-dev python-imaging libjs-jquery python-sphinx python-git python-bibtex \
-		libxmu-dev libxi-dev libcgal-dev help2man libsuitesparse-dev \
-		libopenblas-dev libbz2-dev zlib1g-dev
+		libxmu-dev libxi-dev libcgal-dev help2man libbz2-dev zlib1g-dev \
+		
 
+Some of packages (for example, cmake, eigen3) are mandatory, some of them
+are optional. Watch for notes and warnings/errors, which are shown
+by cmake during configuration step. If the missing package is optional,
+some of Yade features will be disabled (see the messages at the end of configuration).
+		
 Additional packages, which can become mandatory later::
 
-		sudo apt-get install libmetis-dev python-gts python-minieigen \
-
-Some packages, which are listed here, are relatively new and they can absent
+		sudo apt-get install python-gts python-minieigen \
+		
+For effective usage of direct solvers in the fluid coupling, the following libraries are recommended, together with eigen>=3.1: blas, lapack, suitesparse, and metis.
+All four of them are available in many different versions. Different combinations are possible and not all of them will work. The following was found to be effective on ubuntu 12.04 and debian wheezy.
+(openblas provides its own version of lapack, and suitesparse-metis will trigger the installation of parmetis)::
+
+		sudo apt-get install libopenblas-dev libsuitesparse-metis-dev \
+
+Some packages listed here are relatively new and they can be absent
 in your distribution (for example, libmetis-dev or python-gts). They can be 
 installed from our `external PPA <https://launchpad.net/~yade-users/+archive/external/>`_
 or just ignored. In this case some features can be disabled.
 
 If you are using other distribuition, than Debian or its derivatives, you should
-install the software, which is listed above. Their names can differ from the 
+install the softwares listed above. Their names can differ from the 
 names of Debian-packages.
 
-Some of packages (for example, cmake, eigen3) are mandatory, some of them
-are optional. Watch for notes and warnings/errors, which are shown
-by cmake during configuration step. If the missing package is optional,
-some of Yade features will be disabled (see the messages at the end of configuration).
-
-.. warning:: if you have Ubuntu 12.10 or older, you should install libqglviewer-qt4-dev
- package instead of libqglviewer-dev.
+
+
+
 
 
 Compilation

=== modified file 'doc/sphinx/prog.rst'
--- doc/sphinx/prog.rst	2013-09-11 10:53:43 +0000
+++ doc/sphinx/prog.rst	2013-09-12 06:56:25 +0000
@@ -97,7 +97,7 @@
 ---------------------------------------------------
 A frequently used IDE is Kdevelop. We recommend using this software for navigating 
 in the sources, compiling and debugging. Other useful tools for debugging and 
-profiling are Valgrind and KCachegrind. A series a wiki pages are dedicated to 
+profiling are Valgrind and KCachegrind. A series of wiki pages is dedicated to 
 these tools in the `development section <https://yade-dem.org/wiki/Yade#Development>`__ of the wiki.
 
 Hosting and versioning

=== modified file 'doc/sphinx/publications.rst.in'
--- doc/sphinx/publications.rst.in	2011-12-02 17:24:35 +0000
+++ doc/sphinx/publications.rst.in	2014-01-13 17:49:25 +0000
@@ -8,7 +8,7 @@
 
 Citing Yade
 ---------------------
-Corresponding bibtex entries `here <http://bazaar.launchpad.net/~yade-dev/yade/trunk/view/head:/doc/citing_yade.bib>`_. Pdf versions are available for each of them. See also `"Acknowledging Yade" <citing.html>`_.
+Corresponding bibtex entries `here <https://github.com/yade/trunk/blob/master/doc/citing_yade.bib>`_. Pdf versions are available for each of them. See also `"Acknowledging Yade" <citing.html>`_.
 
 @bib2rst.bib2rst('../yade-docref.bib')@
 

=== modified file 'doc/sphinx/templates/index.html'
--- doc/sphinx/templates/index.html	2013-09-26 13:26:34 +0000
+++ doc/sphinx/templates/index.html	2014-01-22 16:41:20 +0000
@@ -5,13 +5,12 @@
   <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>
-   Yade is located at <a href="https://www.yade-dem.org";>www.yade-dem.org</a>, which contains <a href="https://www.yade-dem.org/doc/";>this documentation</a> and <a href="https://www.yade-dem.org/wiki/";>wiki</a>. Development is kindly hosted at <a href="http://www.launchpad.net/yade";>launchpad</a>; it is used for <a href="http://code.launchpad.net/yade";>source code</a>, <a href="http://bugs.launchpad.net/yade";>bug tracking</a>, <a href="http://blueprints.launchpad.net/yade";>planning</a>, <a href="https://launchpad.net/~yade-pkg/+archive/snapshots";>package</a> and <a href="https://launchpad.net/yade/+download";>source</a> downloads</a> and more.
+  Yade is located at <a href="https://www.yade-dem.org";>www.yade-dem.org</a>, which contains <a href="https://www.yade-dem.org/doc/";>this documentation</a> and <a href="https://www.yade-dem.org/wiki/";>wiki</a>. Development is kindly hosted on <a href="http://www.launchpad.net/yade";>launchpad</a> and <a href="https://github.com/yade";> GitHub </a>; they are used for <a href="https://github.com/yade/trunk";>source code</a>, <a href="http://bugs.launchpad.net/yade";>bug tracking</a> and <a href="https://launchpad.net/yade/+download";>source</a> downloads</a> and more.
   </p>
   <p>
   Since March 2012 Yade is using GIT as VCS and placing the source code on 
   <a href="https://github.com/yade/trunk";>github</a>. The Launchpad is importing
-  source code several times per day for the further buiding of "daily"-packages 
-  for Ubuntu.
+  source code several times per day.
   </p>
   <p>
    Please make sure you read the <a href="{{ pathto("citing") }}">"Acknowledging Yade"</a> section if you plan to cite Yade in publications.

=== modified file 'doc/sphinx/user.rst'
--- doc/sphinx/user.rst	2013-10-07 06:14:15 +0000
+++ doc/sphinx/user.rst	2013-12-20 14:12:32 +0000
@@ -1567,7 +1567,7 @@
 	s=bodyStressTensors()
 	stress = s[b.id]**4.*pi/3.*b.shape.radius**3/TW.volume(b.id)
 
-As any other value, the stress can be exported to a vtk file for display in Paraview using :yref:`yade.exporter.VTKExporter`.
+As any other value, the stress can be exported to a vtk file for display in Paraview using :yref:`yade.export.VTKExporter`.
 
 ******************************
 Python specialties and tricks

=== modified file 'doc/yade-articles.bib'
--- doc/yade-articles.bib	2013-08-26 21:57:21 +0000
+++ doc/yade-articles.bib	2014-01-06 09:35:37 +0000
@@ -587,4 +587,17 @@
 	pages={221--235}
 }
 
-
+@article{Hilton2013,
+	title = {Drag force on a spherical intruder in a granular bed at low Froude number},
+	author = {Hilton, J. E. and Tordesillas, A.},
+	journal = {Phys. Rev. E},
+	volume = {88},
+	issue = {6},
+	pages = {062203},
+	numpages = {8},
+	year = {2013},
+	month = {Dec},
+	publisher = {American Physical Society},
+	doi = {10.1103/PhysRevE.88.062203},
+	url = {http://link.aps.org/doi/10.1103/PhysRevE.88.062203}
+}

=== modified file 'doc/yade-conferences.bib'
--- doc/yade-conferences.bib	2013-08-26 21:53:51 +0000
+++ doc/yade-conferences.bib	2014-01-13 17:49:25 +0000
@@ -592,12 +592,22 @@
 }
 
 @InProceedings{Maurin2013,
-  title={Discrete element modelling of bedload transport},
-  author={Maurin, Raphael and Chareyre, Bruno and Chauchat, Julien and Frey, Philippe},
-  booktitle={Proceedings of THESIS 2013, Two-pHase modElling for Sediment dynamIcS in Geophysical Flows},
-  adress = {Chatou, France},
-  pages={6p},
-  url = {https://www.yade-dem.org/publi/Maurin_et_al_THESIS_meta.pdf},
-  year={2013}
+	title={Discrete element modelling of bedload transport},
+	author={Maurin, Raphael and Chareyre, Bruno and Chauchat, Julien and Frey, Philippe},
+	booktitle={Proceedings of THESIS 2013, Two-pHase modElling for Sediment dynamIcS in Geophysical Flows},
+	adress = {Chatou, France},
+	pages={6p},
+	url = {https://www.yade-dem.org/publi/Maurin_et_al_THESIS_meta.pdf},
+	year={2013}
 }
 
+@InProceedings{Elias2013,
+	author={Eliáš, J.},
+	title={Dem simulation of railway ballast using polyhedral elemental shapes},
+	journal={Particle-Based Methods III: Fundamentals and Applications - Proceedings of the 3rd International Conference on Particle-based MethodsFundamentals and Applications, Particles 2013},
+	year={2013},
+	pages={247-256},
+	url={https://www.vutbr.cz/www_base/gigadisk.php?i=95194aa9a},
+	document_type={Conference Paper},
+	source={Scopus},
+}

=== added directory 'examples/adaptiveintegrator'
=== added file 'examples/adaptiveintegrator/simple-scene-plot-NewtonIntegrator.py'
--- examples/adaptiveintegrator/simple-scene-plot-NewtonIntegrator.py	1970-01-01 00:00:00 +0000
+++ examples/adaptiveintegrator/simple-scene-plot-NewtonIntegrator.py	2014-02-17 14:31:35 +0000
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+import matplotlib
+matplotlib.use('TkAgg')
+
+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.0,gravity=(0,0,-9.81)),
+	###
+	### NOTE this extra engine:
+	###
+	### You want snapshot to be taken every 1 sec (realTimeLim) or every 50 iterations (iterLim),
+	### whichever comes soones. virtTimeLim attribute is unset, hence virtual time period is not taken into account.
+	PyRunner(iterPeriod=20,command='myAddPlotData()')
+]
+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 yade import plot
+## we will have 2 plots:
+## 1. t as function of i (joke test function)
+## 2. i as function of t on left y-axis ('|||' makes the separation) and z_sph, v_sph (as green circles connected with line) and z_sph_half again as function of t
+plot.plots={'i':('t'),'t':('z_sph',None,('v_sph','go-'),'z_sph_half')}
+
+## this function is called by plotDataCollector
+## it should add data with the labels that we will plot
+## if a datum is not specified (but exists), it will be NaN and will not be plotted
+def myAddPlotData():
+	sph=O.bodies[1]
+	## store some numbers under some labels
+	plot.addData(t=O.time,i=O.iter,z_sph=sph.state.pos[2],z_sph_half=.5*sph.state.pos[2],v_sph=sph.state.vel.norm())
+print "Now calling plot.plot() to show the figures. The timestep is artificially low so that you can watch graphs being updated live."
+plot.liveInterval=.2
+plot.plot(subPlots=False)
+O.run(int(5./O.dt));
+#plot.saveGnuplot('/tmp/a')
+## you can also access the data in plot.data['i'], plot.data['t'] etc, under the labels they were saved.

=== added file 'examples/adaptiveintegrator/simple-scene-plot-RungeKuttaCashKarp54.py'
--- examples/adaptiveintegrator/simple-scene-plot-RungeKuttaCashKarp54.py	1970-01-01 00:00:00 +0000
+++ examples/adaptiveintegrator/simple-scene-plot-RungeKuttaCashKarp54.py	2014-02-17 14:31:35 +0000
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+# 	Burak ER
+#	burak.er@xxxxxxxxxx
+# 	github.com/burak-er
+#	Mechanical Engineering Department
+#	Bursa Technical University
+#
+# -*- coding: utf-8 -*-
+import matplotlib
+matplotlib.use('TkAgg')
+
+# Use an integrator engine that is derived from the interface Integrator.
+
+#RungeKuttaCashKarp54Integrator integrator performs one step of simulation for the given tolerances. Whether the time step is given, it completes it then stops.
+
+integrator=RungeKuttaCashKarp54Integrator([
+	ForceResetter(),
+	GeneralIntegratorInsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Box_Aabb()]),
+	InteractionLoop(
+		[Ig2_Sphere_Sphere_ScGeom(),Ig2_Box_Sphere_ScGeom()],
+		[Ip2_FrictMat_FrictMat_FrictPhys()],
+		[Law2_ScGeom_FrictPhys_CundallStrack()]
+	),
+	GravityEngine(gravity=Vector3(0,0,-9.81)),
+	PyRunner(virtPeriod=1e-99,command='myAddPlotData()')#use virtPeriod on this integrator.
+
+]);
+
+#Tolerances can be set for the optimum accuracy
+integrator.rel_err=1e-6;
+integrator.abs_err=1e-6;
+
+O.engines=[integrator,
+]
+
+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=1e-2# this signifies the endpoint. It is not much important for the accuracy of the integration where accuracy is defined by rel_err and abs_err of the integrator.
+
+
+
+############################################
+##### now the part pertaining to plots #####
+############################################
+
+from yade import plot
+## we will have 2 plots:
+## 1. t as function of i (joke test function)
+## 2. i as function of t on left y-axis ('|||' makes the separation) and z_sph, v_sph (as green circles connected with line) and z_sph_half again as function of t
+plot.plots={'i':('t'),'t':('z_sph',None,('v_sph','go-'),'z_sph_half')}
+
+## this function is called by plotDataCollector
+## it should add data with the labels that we will plot
+## if a datum is not specified (but exists), it will be NaN and will not be plotted
+def myAddPlotData():
+	sph=O.bodies[1]
+	## store some numbers under some labels
+	plot.addData(t=O.time,i=O.iter,z_sph=sph.state.pos[2],z_sph_half=.5*sph.state.pos[2],v_sph=sph.state.vel.norm())
+print "Now calling plot.plot() to show the figures. The timestep is artificially low so that you can watch graphs being updated live."
+plot.liveInterval=.2
+plot.plot(subPlots=False)
+print "Number of threads ", os.environ['OMP_NUM_THREADS']
+O.run(int(5./O.dt));
+#plot.saveGnuplot('/tmp/a')
+## you can also access the data in plot.data['i'], plot.data['t'] etc, under the labels they were saved.

=== added file 'examples/billiard.py'
--- examples/billiard.py	1970-01-01 00:00:00 +0000
+++ examples/billiard.py	2014-02-16 17:35:46 +0000
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# The script was implemented to check the following task
+# http://math.stackexchange.com/questions/658871/perfectly-centered-break-of-a-perfectly-aligned-pool-ball-rack/659318#659318
+
+massBall   = 1.0
+radiusBall = 1.0
+rowsN = 5
+velBall = 10.0
+
+vBall = 4.0/3.0 * math.pi * math.pow(radiusBall, 3.0)
+rhoBall = massBall/vBall
+
+
+## PhysicalParameters 
+Density=rhoBall
+frictionAngle=0.0
+kn = 10e+11
+ks = 10e+11
+cn = 0.0
+cs = 0.0
+
+## Import wall's geometry
+param = {'kn':kn*2.0, 'ks':ks*2.0, 'cn':cn*2.0, 'cs':cs*2.0}
+sphereMat=O.materials.append(ViscElMat(density=Density,frictionAngle=frictionAngle,**param))
+
+## Spheres
+sphereIds = []
+for r in range(0,rowsN):
+  yPos = r*pow(3.0, 1.0/2.0)*radiusBall
+  for i in range(r+1):
+    xPos = i*2*radiusBall - r*pow(radiusBall, 3.0/2.0)
+    sphereIds.append(O.bodies.append(sphere([xPos,yPos,0.0],radiusBall,material=sphereMat)))
+
+## schlagBall
+
+schlagBall = O.bodies.append(sphere([0.0,-2.0*radiusBall,0.0],radiusBall,material=sphereMat))
+
+O.bodies[schlagBall].state.vel=Vector3(0,velBall,0)
+## Timestep 
+O.dt=.01*PWaveTimeStep()
+
+## Engines 
+O.engines=[
+  ForceResetter(),
+  InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()]),
+  InteractionLoop(
+    [Ig2_Sphere_Sphere_ScGeom(), Ig2_Facet_Sphere_ScGeom()],
+    [Ip2_ViscElMat_ViscElMat_ViscElPhys()],
+    [Law2_ScGeom_ViscElPhys_Basic()],
+  ),
+  NewtonIntegrator(damping=0),
+]
+
+from yade import qt
+qt.View()
+#O.run(int(0.3/O.dt), True)

=== modified file 'examples/clumps/addToClump-example.py'
--- examples/clumps/addToClump-example.py	2013-08-21 06:35:10 +0000
+++ examples/clumps/addToClump-example.py	2013-12-03 07:53:08 +0000
@@ -3,6 +3,8 @@
 
 '''This example shows usage of addToClump() and appendClumped().'''
 
+from yade import pack,export,qt
+
 #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]
@@ -81,3 +83,5 @@
 O.dt=1e-6
 
 print '\nPress Play button ... '
+renderer = qt.Renderer()
+qt.View()

=== added file 'examples/clumps/save-load-clumps.py'
--- examples/clumps/save-load-clumps.py	1970-01-01 00:00:00 +0000
+++ examples/clumps/save-load-clumps.py	2013-12-09 12:32:37 +0000
@@ -0,0 +1,83 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+'''This example shows usage of save and load clumps.'''
+
+from yade import pack,export,qt,ymport
+
+#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]
+			print 'inertia:',b.state.inertia
+			print 'mass:',b.state.mass,'\n'
+
+
+#### show how to use addToClump():
+
+#create a new sphere:
+id_new=O.bodies.append(sphere([0,0.2,1], material=Mat, radius=0.5))
+
+#add a sphere to the clump:
+O.bodies.addToClump([id_new],id_clump1)
+
+#add a clump to a clump:
+O.bodies.addToClump([id_clump2],id_clump1)
+
+print '\nSTATE after adding the second clump to clump ------------'
+getClumpInfo()
+
+print "Save clumps"
+export.textClumps("savedClumps.txt")
+print "Load clumps"
+ymport.textClumps("savedClumps.txt", shift=Vector3(0,0,1.5))
+
+print "After saving"
+getClumpInfo()
+
+O.dt=1e-6
+
+print '\nPress Play button ... '
+renderer = qt.Renderer()
+qt.View()

=== modified file 'examples/concrete/triax.py'
--- examples/concrete/triax.py	2013-08-09 02:27:56 +0000
+++ examples/concrete/triax.py	2013-12-09 16:20:17 +0000
@@ -24,7 +24,7 @@
 	# prestress
 	preStress = -3e6,
 	# axial strain rate
-	strainRate = -20,
+	strainRate = -100,
 
 	# assamlby parameters
 	rParticle = .075e-3, #
@@ -57,8 +57,9 @@
 # spheres
 pred = pack.inCylinder((0,0,0),(0,0,height),.5*width) if testType=='cyl' else pack.inAlignedBox((-.5*width,-.5*width,0),(.5*width,.5*width,height)) if testType=='cube' else None
 sp=SpherePack()
-sp = pack.randomDensePack(pred,spheresInCell=2000,radius=rParticle,memoizeDb='/tmp/triaxTestOnCylinder.sqlite',material=concMat,returnSpherePack=True)
-spheres=sp.toSimulation(color=(0,1,1))
+sp = pack.randomDensePack(pred,spheresInCell=2000,radius=rParticle,memoizeDb='/tmp/triaxTestOnCylinder.sqlite',returnSpherePack=True)
+spheres=sp.toSimulation(color=(0,1,1),material=concMat)
+
 # bottom and top of specimen. Will have prescribed velocity
 bot = [O.bodies[s] for s in spheres if O.bodies[s].state.pos[2]<rParticle*bcCoeff]
 top = [O.bodies[s] for s in spheres if O.bodies[s].state.pos[2]>height-rParticle*bcCoeff]

=== modified file 'examples/packs/packs.py'
--- examples/packs/packs.py	2013-10-04 11:58:44 +0000
+++ examples/packs/packs.py	2014-01-06 13:59:54 +0000
@@ -112,11 +112,6 @@
 
 O.bodies.append(wall((0,0,-10),axis=2))
 
-try:
-	from yade import qt
-	qt.Controller()
-	qt.View()
-except ImportError: pass
 
 O.engines=[
 	#SubdomainBalancer(colorize=True,initRun=True,iterPeriod=100),
@@ -153,6 +148,12 @@
 
 # we don't care about physical accuracy here, (over)critical step is fine as long as the simulation doesn't explode
 O.dt=PWaveTimeStep()
+O.run(1,True)
+try:
+	from yade import qt
+	qt.Controller()
+	qt.View()
+except ImportError: pass
 O.saveTmp()
 O.timingEnabled=True
 #O.run(10000,True)

=== added directory 'examples/stl-gts'
=== added file 'examples/stl-gts/README'
--- examples/stl-gts/README	1970-01-01 00:00:00 +0000
+++ examples/stl-gts/README	2013-12-03 07:47:09 +0000
@@ -0,0 +1,7 @@
+This example shows, how to perform the following conversion:
+GEO->STL->GTS->Yade(clumps)
+
+Then GTS-file (mesh) is importing into Yade-Script and new spheres
+are adding as a clump within the volume of this mesh.
+
+The script requires gmsh and libgts-bin installed.

=== added file 'examples/stl-gts/cone.geo'
--- examples/stl-gts/cone.geo	1970-01-01 00:00:00 +0000
+++ examples/stl-gts/cone.geo	2013-12-03 07:47:09 +0000
@@ -0,0 +1,38 @@
+acc = 20.0/1000.0;
+D = 280.0/2.0/1000.0;
+d = 180.0/2.0/1000.0;
+h = 180.0/1000.0;
+Point(1) = {0.0, 0.0, 0.0, acc};
+Point(2) = {0.0, D, 0.0, acc};
+Point(3) = {0.0, -D, 0.0, acc};
+Point(4) = {D, 0.0, 0.0, acc};
+Point(5) = {-D, 0.0, 0.0, acc};
+Point(6) = {0.0, 0.0, h, acc};
+Circle(1) = {2, 1, 4};
+Circle(2) = {4, 1, 3};
+Circle(3) = {3, 1, 5};
+Circle(4) = {5, 1, 2};
+Line(5) = {2, 1};
+Line(6) = {2, 6};
+Line(7) = {4, 1};
+Line(8) = {4, 6};
+Line(9) = {3, 1};
+Line(10) = {3, 6};
+Line(11) = {5, 1};
+Line(12) = {5, 6};
+Line Loop(13) = {1, 7, -5};
+Plane Surface(14) = {13};
+Line Loop(15) = {2, 9, -7};
+Plane Surface(16) = {15};
+Line Loop(17) = {3, 11, -9};
+Plane Surface(18) = {17};
+Line Loop(19) = {4, 5, -11};
+Plane Surface(20) = {19};
+Line Loop(21) = {3, 12, -10};
+Ruled Surface(22) = {21};
+Line Loop(23) = {4, 6, -12};
+Ruled Surface(24) = {23};
+Line Loop(25) = {1, 8, -6};
+Ruled Surface(26) = {25};
+Line Loop(27) = {2, 10, -8};
+Ruled Surface(28) = {27};

=== added file 'examples/stl-gts/convert2stl.sh'
--- examples/stl-gts/convert2stl.sh	1970-01-01 00:00:00 +0000
+++ examples/stl-gts/convert2stl.sh	2013-12-03 07:47:09 +0000
@@ -0,0 +1,3 @@
+#!/bin/bash
+gmsh -2 cone.geo -o cone.stl
+stl2gts -r < cone.stl > cone.gts

=== added file 'examples/stl-gts/gts-stl.py'
--- examples/stl-gts/gts-stl.py	1970-01-01 00:00:00 +0000
+++ examples/stl-gts/gts-stl.py	2013-12-03 07:47:09 +0000
@@ -0,0 +1,42 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# © 2009 Václav Šmilauer <eudoxos@xxxxxxxx>
+# © 2013 Anton Gladky <gladk@xxxxxxxxxx>
+
+from yade import pack
+import gts, os.path, locale
+
+surf=gts.read(open('cone.gts'))
+
+if surf.is_closed():
+	pred=pack.inGtsSurface(surf)
+	aabb=pred.aabb()
+	dim0=aabb[1][0]-aabb[0][0]; radius=dim0/70. # get some characteristic dimension, use it for radius
+	O.bodies.appendClumped(pack.regularHexa(pred,radius=radius,gap=radius/4.))
+	surf.translate(0,-(aabb[1][1]-aabb[0][1])/2.0,-(aabb[1][2]-aabb[0][2])) # move surface down so that facets are underneath the falling spheres
+O.bodies.append(pack.gtsSurface2Facets(surf,wire=True))
+
+O.engines=[
+	ForceResetter(),
+	InsertionSortCollider([Bo1_Sphere_Aabb(),Bo1_Facet_Aabb()],label='collider'),
+	InteractionLoop(
+		[Ig2_Sphere_Sphere_L3Geom(),Ig2_Facet_Sphere_L3Geom()],
+		[Ip2_FrictMat_FrictMat_FrictPhys()],
+		[Law2_L3Geom_FrictPhys_ElPerfPl()],
+	),
+	NewtonIntegrator(damping=.1,gravity=[0,0,-500.0]),
+	PyRunner(iterPeriod=1000,command='timing.stats(); O.pause();'),
+	PyRunner(iterPeriod=10,command='addPlotData()')
+]
+O.dt=.7*PWaveTimeStep()
+O.saveTmp()
+O.timingEnabled=True
+O.trackEnergy=True
+from yade import plot
+plot.plots={'i':('total',O.energy.keys,)}
+def addPlotData(): plot.addData(i=O.iter,total=O.energy.total(),**O.energy)
+plot.plot(subPlots=False)
+
+from yade import timing
+from yade import qt
+qt.View()

=== modified file 'examples/test/batch/sim.py'
--- examples/test/batch/sim.py	2013-03-28 11:15:45 +0000
+++ examples/test/batch/sim.py	2014-01-23 18:08:34 +0000
@@ -1,4 +1,4 @@
-from yade import *
+
 readParamsFromTable(unknownOk=True,
 	important=6,
 	unimportant='foo',

=== added directory 'examples/test/paraview-spheres-solid-section'
=== added file 'examples/test/paraview-spheres-solid-section/export_text.py'
--- examples/test/paraview-spheres-solid-section/export_text.py	1970-01-01 00:00:00 +0000
+++ examples/test/paraview-spheres-solid-section/export_text.py	2014-02-17 16:37:16 +0000
@@ -0,0 +1,12 @@
+from yade import pack, export
+pred = pack.inAlignedBox((0,0,0),(10,10,10))
+O.bodies.append(pack.randomDensePack(pred,radius=1.,rRelFuzz=.5,spheresInCell=500,memoizeDb='/tmp/pack.db'))
+
+export.textExt('/tmp/test.txt',format='x_y_z_r_attrs',attrs=('b.state.pos.norm()','b.state.pos'),comment='dstN dstV_x dstV_y dstV_z')
+# text2vtk and text2vtkSection function can be copy-pasted from yade/py/export.py into separate py file to avoid executing yade or to use pure python
+export.text2vtk('/tmp/test.txt','/tmp/test.vtk')
+export.text2vtkSection('/tmp/test.txt','/tmp/testSection.vtk',point=(5,5,5),normal=(1,1,1))
+
+# now open paraview, click "Tools" menu -> "Python Shell", click "Run Script", choose "pv_section.py" from this directiory
+# or just run python pv_section.py
+# and enjoy :-)

=== added file 'examples/test/paraview-spheres-solid-section/pv_section.py'
--- examples/test/paraview-spheres-solid-section/pv_section.py	1970-01-01 00:00:00 +0000
+++ examples/test/paraview-spheres-solid-section/pv_section.py	2014-02-17 16:37:16 +0000
@@ -0,0 +1,660 @@
+try: paraview.simple
+except: from paraview.simple import *
+paraview.simple._DisableFirstRenderCameraReset()
+
+RenderView1 = CreateRenderView()
+RenderView1.LightSpecularColor = [1.0, 1.0, 1.0]
+RenderView1.KeyLightAzimuth = 10.0
+RenderView1.UseTexturedBackground = 0
+RenderView1.UseLight = 1
+RenderView1.CameraPosition = [-10.901121443539559, -17.271355476388358, 4.309974877565033]
+RenderView1.FillLightKFRatio = 3.0
+RenderView1.Background2 = [0.0, 0.0, 0.165]
+RenderView1.FillLightAzimuth = -10.0
+RenderView1.LODResolution = 50.0
+RenderView1.BackgroundTexture = []
+RenderView1.InteractionMode = '3D'
+RenderView1.StencilCapable = 1
+RenderView1.LightIntensity = 1.0
+RenderView1.CameraFocalPoint = [4.732498500000004, 5.045734999999994, 4.874767500000023]
+RenderView1.ImageReductionFactor = 2
+RenderView1.CameraViewAngle = 30.0
+RenderView1.CameraParallelScale = 7.0538593576100945
+RenderView1.EyeAngle = 2.0
+RenderView1.HeadLightKHRatio = 3.0
+RenderView1.StereoRender = 0
+RenderView1.KeyLightIntensity = 0.75
+RenderView1.BackLightAzimuth = 110.0
+RenderView1.OrientationAxesInteractivity = 0
+RenderView1.UseInteractiveRenderingForSceenshots = 0
+RenderView1.UseOffscreenRendering = 0
+RenderView1.Background = [1.0, 1.0, 1.0]
+RenderView1.UseOffscreenRenderingForScreenshots = 0
+RenderView1.NonInteractiveRenderDelay = 2
+RenderView1.CenterOfRotation = [4.7324985, 5.045735, 4.8747675]
+RenderView1.CameraParallelProjection = 0
+RenderView1.CompressorConfig = 'vtkSquirtCompressor 0 3'
+RenderView1.HeadLightWarmth = 0.5
+RenderView1.MaximumNumberOfPeels = 4
+RenderView1.LightDiffuseColor = [1.0, 1.0, 1.0]
+RenderView1.StereoType = 'Red-Blue'
+RenderView1.DepthPeeling = 1
+RenderView1.BackLightKBRatio = 3.5
+RenderView1.StereoCapableWindow = 1
+RenderView1.CameraViewUp = [-0.818931483577863, 0.5738512869077476, -0.006776851723502143]
+RenderView1.LightType = 'HeadLight'
+RenderView1.LightAmbientColor = [1.0, 1.0, 1.0]
+RenderView1.RemoteRenderThreshold = 3.0
+RenderView1.CacheKey = 0.0
+RenderView1.UseCache = 0
+RenderView1.KeyLightElevation = 50.0
+RenderView1.CenterAxesVisibility = 0
+RenderView1.MaintainLuminance = 0
+RenderView1.StillRenderImageReductionFactor = 1
+RenderView1.BackLightWarmth = 0.5
+RenderView1.FillLightElevation = -75.0
+RenderView1.MultiSamples = 0
+RenderView1.FillLightWarmth = 0.4
+RenderView1.AlphaBitPlanes = 1
+RenderView1.LightSwitch = 0
+RenderView1.OrientationAxesVisibility = 0
+RenderView1.CameraClippingRange = [14.893135346284218, 43.89470107765568]
+RenderView1.BackLightElevation = 0.0
+RenderView1.ViewTime = 0.0
+RenderView1.OrientationAxesOutlineColor = [1.0, 1.0, 1.0]
+RenderView1.LODThreshold = 5.0
+RenderView1.CollectGeometryThreshold = 100.0
+RenderView1.UseGradientBackground = 0
+RenderView1.KeyLightWarmth = 0.6
+RenderView1.OrientationAxesLabelColor = [1.0, 1.0, 1.0]
+
+test_vtk = LegacyVTKReader( guiName="test.vtk", FileNames=['/tmp/test.vtk'] )
+
+Glyph1 = Glyph( guiName="Glyph1", RandomMode=1, GlyphTransform="Transform2", GlyphType="Sphere", MaximumNumberofPoints=5000, ScaleMode='scalar', MaskPoints=0, Vectors=['POINTS', ''], SetScaleFactor=1.0, Scalars=['POINTS', 'radius'], Orient=1 )
+Glyph1.GlyphType.StartTheta = 0.0
+Glyph1.GlyphType.ThetaResolution = 12
+Glyph1.GlyphTransform.Rotate = [0.0, 0.0, 0.0]
+Glyph1.GlyphTransform.Translate = [0.0, 0.0, 0.0]
+Glyph1.GlyphType.PhiResolution = 12
+Glyph1.GlyphType.EndTheta = 360.0
+Glyph1.GlyphType.EndPhi = 180.0
+Glyph1.GlyphType.Center = [0.0, 0.0, 0.0]
+Glyph1.GlyphType.Radius = 1.0
+Glyph1.GlyphTransform.Scale = [1.0, 1.0, 1.0]
+Glyph1.GlyphType.StartPhi = 0.0
+
+Clip2 = Clip( guiName="Clip2", InsideOut=0, UseValueAsOffset=0, Scalars=['POINTS', 'radius'], Value=0.0, ClipType="Plane" )
+Clip2.ClipType.Normal = [1.0, 1.0, 1.0]
+Clip2.ClipType.Origin = [5.0, 5.0, 5.0]
+Clip2.ClipType.Offset = 0.0
+
+testSection_vtk = LegacyVTKReader( guiName="testSection.vtk", FileNames=['/tmp/testSection.vtk'] )
+
+Glyph3 = Glyph( guiName="Glyph3", ScaleMode='scalar', GlyphType="Cylinder", MaskPoints=0, RandomMode=1, Vectors=['POINTS', 'normal'], GlyphTransform="Transform2", Scalars=['POINTS', 'radius'], MaximumNumberofPoints=5000, SetScaleFactor=1.0, Orient=1 )
+Glyph3.GlyphType.Capping = 1
+Glyph3.GlyphType.Height = 0.01
+Glyph3.GlyphTransform.Rotate = [0.0, 0.0, -90.0]
+Glyph3.GlyphType.Radius = 1.0
+Glyph3.GlyphTransform.Translate = [0.0, 0.0, 0.0]
+Glyph3.GlyphType.Center = [0.0, 0.0, 0.0]
+Glyph3.GlyphType.Resolution = 18
+Glyph3.GlyphTransform.Scale = [1.0, 1.0, 1.0]
+
+a1_radius_PiecewiseFunction = CreatePiecewiseFunction( Points=[0.0, 0.0, 0.5, 0.0, 1.0, 1.0, 0.5, 0.0] )
+
+a1_radiusOrig_PiecewiseFunction = CreatePiecewiseFunction( Points=[0.0, 0.0, 0.5, 0.0, 1.0, 1.0, 0.5, 0.0] )
+
+a1_radius_PVLookupTable = GetLookupTableForArray( "radius", 1, Discretize=1, RGBPoints=[0.522954, 0.0, 0.0, 1.0, 1.42914, 1.0, 0.0, 0.0], UseLogScale=0, VectorComponent=0, NanColor=[0.498039, 0.498039, 0.498039], NumberOfTableValues=256, ColorSpace='HSV', VectorMode='Magnitude', HSVWrap=0, ScalarRangeInitialized=1.0, LockScalarRange=1 )
+
+a1_radiusOrig_PVLookupTable = GetLookupTableForArray( "radiusOrig", 1, Discretize=1, RGBPoints=[0.54491, 0.0, 0.0, 1.0, 1.41118, 1.0, 0.0, 0.0], UseLogScale=0, VectorComponent=0, NanColor=[0.498039, 0.498039, 0.498039], NumberOfTableValues=256, ColorSpace='HSV', VectorMode='Magnitude', HSVWrap=0, ScalarRangeInitialized=1.0, LockScalarRange=1 )
+
+SetActiveSource(test_vtk)
+DataRepresentation1 = Show()
+DataRepresentation1.CubeAxesZAxisVisibility = 1
+DataRepresentation1.SelectionPointLabelColor = [0.5, 0.5, 0.5]
+DataRepresentation1.SelectionPointFieldDataArrayName = 'radius'
+DataRepresentation1.SuppressLOD = 0
+DataRepresentation1.CubeAxesXGridLines = 0
+DataRepresentation1.CubeAxesYAxisTickVisibility = 1
+DataRepresentation1.CubeAxesColor = [1.0, 1.0, 1.0]
+DataRepresentation1.Position = [0.0, 0.0, 0.0]
+DataRepresentation1.BackfaceRepresentation = 'Follow Frontface'
+DataRepresentation1.SelectionOpacity = 1.0
+DataRepresentation1.SelectionPointLabelShadow = 0
+DataRepresentation1.CubeAxesYGridLines = 0
+DataRepresentation1.CubeAxesZAxisRange = [0.0, 1.0]
+DataRepresentation1.OrientationMode = 'Direction'
+DataRepresentation1.Source.TipResolution = 6
+DataRepresentation1.ScaleMode = 'No Data Scaling Off'
+DataRepresentation1.Diffuse = 1.0
+DataRepresentation1.SelectionUseOutline = 0
+DataRepresentation1.CubeAxesZTitle = 'Z-Axis'
+DataRepresentation1.Specular = 0.1
+DataRepresentation1.SelectionVisibility = 1
+DataRepresentation1.InterpolateScalarsBeforeMapping = 1
+DataRepresentation1.CubeAxesZAxisTickVisibility = 1
+DataRepresentation1.Origin = [0.0, 0.0, 0.0]
+DataRepresentation1.CubeAxesVisibility = 0
+DataRepresentation1.Scale = [1.0, 1.0, 1.0]
+DataRepresentation1.SelectionCellLabelJustification = 'Left'
+DataRepresentation1.DiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation1.SelectionCellLabelOpacity = 1.0
+DataRepresentation1.Source = "Arrow"
+DataRepresentation1.Source.Invert = 0
+DataRepresentation1.Masking = 0
+DataRepresentation1.Opacity = 1.0
+DataRepresentation1.LineWidth = 1.0
+DataRepresentation1.MeshVisibility = 0
+DataRepresentation1.Visibility = 1
+DataRepresentation1.SelectionCellLabelFontSize = 18
+DataRepresentation1.CubeAxesCornerOffset = 0.0
+DataRepresentation1.SelectionPointLabelJustification = 'Left'
+DataRepresentation1.SelectionPointLabelVisibility = 0
+DataRepresentation1.SelectOrientationVectors = ''
+DataRepresentation1.CubeAxesTickLocation = 'Inside'
+DataRepresentation1.CubeAxesXAxisMinorTickVisibility = 1
+DataRepresentation1.CubeAxesYAxisVisibility = 1
+DataRepresentation1.SelectionPointLabelFontFamily = 'Arial'
+DataRepresentation1.Source.ShaftResolution = 6
+DataRepresentation1.CubeAxesFlyMode = 'Closest Triad'
+DataRepresentation1.SelectScaleArray = ''
+DataRepresentation1.CubeAxesYTitle = 'Y-Axis'
+DataRepresentation1.ColorAttributeType = 'POINT_DATA'
+DataRepresentation1.SpecularPower = 100.0
+DataRepresentation1.Texture = []
+DataRepresentation1.SelectionCellLabelShadow = 0
+DataRepresentation1.AmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation1.MapScalars = 1
+DataRepresentation1.PointSize = 2.0
+DataRepresentation1.Source.TipLength = 0.35
+DataRepresentation1.SelectionCellLabelFormat = ''
+DataRepresentation1.Scaling = 0
+DataRepresentation1.StaticMode = 0
+DataRepresentation1.SelectionCellLabelColor = [0.0, 1.0, 0.0]
+DataRepresentation1.Source.TipRadius = 0.1
+DataRepresentation1.EdgeColor = [0.0, 0.0, 0.5000076295109483]
+DataRepresentation1.CubeAxesXAxisTickVisibility = 1
+DataRepresentation1.SelectionCellLabelVisibility = 0
+DataRepresentation1.NonlinearSubdivisionLevel = 1
+DataRepresentation1.CubeAxesXAxisRange = [0.0, 1.0]
+DataRepresentation1.Representation = 'Surface'
+DataRepresentation1.CubeAxesYAxisRange = [0.0, 1.0]
+DataRepresentation1.CustomBounds = [0.0, 1.0, 0.0, 1.0, 0.0, 1.0]
+DataRepresentation1.Orientation = [0.0, 0.0, 0.0]
+DataRepresentation1.CubeAxesEnableCustomAxisRange = 0
+DataRepresentation1.CubeAxesXTitle = 'X-Axis'
+DataRepresentation1.CubeAxesInertia = 1
+DataRepresentation1.BackfaceOpacity = 1.0
+DataRepresentation1.SelectionCellFieldDataArrayName = 'vtkOriginalCellIds'
+DataRepresentation1.SelectionColor = [1.0, 0.0, 1.0]
+DataRepresentation1.Ambient = 0.0
+DataRepresentation1.SelectionPointLabelFontSize = 18
+DataRepresentation1.ScaleFactor = 0.8360145000000001
+DataRepresentation1.BackfaceAmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation1.Source.ShaftRadius = 0.03
+DataRepresentation1.SelectMaskArray = ''
+DataRepresentation1.SelectionLineWidth = 2.0
+DataRepresentation1.CubeAxesZAxisMinorTickVisibility = 1
+DataRepresentation1.CubeAxesXAxisVisibility = 1
+DataRepresentation1.Interpolation = 'Gouraud'
+DataRepresentation1.SelectionCellLabelFontFamily = 'Arial'
+DataRepresentation1.SelectionCellLabelItalic = 0
+DataRepresentation1.CubeAxesYAxisMinorTickVisibility = 1
+DataRepresentation1.CubeAxesZGridLines = 0
+DataRepresentation1.SelectionPointLabelFormat = ''
+DataRepresentation1.SelectionPointLabelOpacity = 1.0
+DataRepresentation1.BackfaceDiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation1.Pickable = 1
+DataRepresentation1.CustomBoundsActive = [0, 0, 0]
+DataRepresentation1.SelectionRepresentation = 'Wireframe'
+DataRepresentation1.SelectionPointLabelBold = 0
+DataRepresentation1.ColorArrayName = 'radius'
+DataRepresentation1.SelectionPointLabelItalic = 0
+DataRepresentation1.AllowSpecularHighlightingWithScalarColoring = 0
+DataRepresentation1.SpecularColor = [1.0, 1.0, 1.0]
+DataRepresentation1.LookupTable = a1_radius_PVLookupTable
+DataRepresentation1.SelectionPointSize = 5.0
+DataRepresentation1.SelectionCellLabelBold = 0
+DataRepresentation1.Orient = 0
+
+SetActiveSource(Glyph1)
+DataRepresentation3 = Show()
+DataRepresentation3.CubeAxesZAxisVisibility = 1
+DataRepresentation3.SelectionPointLabelColor = [0.5, 0.5, 0.5]
+DataRepresentation3.SelectionPointFieldDataArrayName = 'radius'
+DataRepresentation3.SuppressLOD = 0
+DataRepresentation3.CubeAxesXGridLines = 0
+DataRepresentation3.CubeAxesYAxisTickVisibility = 1
+DataRepresentation3.CubeAxesColor = [1.0, 1.0, 1.0]
+DataRepresentation3.Position = [0.0, 0.0, 0.0]
+DataRepresentation3.BackfaceRepresentation = 'Follow Frontface'
+DataRepresentation3.SelectionOpacity = 1.0
+DataRepresentation3.SelectionPointLabelShadow = 0
+DataRepresentation3.CubeAxesYGridLines = 0
+DataRepresentation3.CubeAxesZAxisRange = [0.0, 1.0]
+DataRepresentation3.OrientationMode = 'Direction'
+DataRepresentation3.Source.TipResolution = 6
+DataRepresentation3.ScaleMode = 'No Data Scaling Off'
+DataRepresentation3.Diffuse = 1.0
+DataRepresentation3.SelectionUseOutline = 0
+DataRepresentation3.CubeAxesZTitle = 'Z-Axis'
+DataRepresentation3.Specular = 0.1
+DataRepresentation3.SelectionVisibility = 1
+DataRepresentation3.InterpolateScalarsBeforeMapping = 1
+DataRepresentation3.CubeAxesZAxisTickVisibility = 1
+DataRepresentation3.Origin = [0.0, 0.0, 0.0]
+DataRepresentation3.CubeAxesVisibility = 0
+DataRepresentation3.Scale = [1.0, 1.0, 1.0]
+DataRepresentation3.SelectionCellLabelJustification = 'Left'
+DataRepresentation3.DiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation3.SelectionCellLabelOpacity = 1.0
+DataRepresentation3.Source = "Arrow"
+DataRepresentation3.Source.Invert = 0
+DataRepresentation3.Masking = 0
+DataRepresentation3.Opacity = 1.0
+DataRepresentation3.LineWidth = 1.0
+DataRepresentation3.MeshVisibility = 0
+DataRepresentation3.Visibility = 0
+DataRepresentation3.SelectionCellLabelFontSize = 18
+DataRepresentation3.CubeAxesCornerOffset = 0.0
+DataRepresentation3.SelectionPointLabelJustification = 'Left'
+DataRepresentation3.SelectionPointLabelVisibility = 0
+DataRepresentation3.SelectOrientationVectors = ''
+DataRepresentation3.CubeAxesTickLocation = 'Inside'
+DataRepresentation3.CubeAxesXAxisMinorTickVisibility = 1
+DataRepresentation3.CubeAxesYAxisVisibility = 1
+DataRepresentation3.SelectionPointLabelFontFamily = 'Arial'
+DataRepresentation3.Source.ShaftResolution = 6
+DataRepresentation3.CubeAxesFlyMode = 'Closest Triad'
+DataRepresentation3.SelectScaleArray = ''
+DataRepresentation3.CubeAxesYTitle = 'Y-Axis'
+DataRepresentation3.ColorAttributeType = 'POINT_DATA'
+DataRepresentation3.SpecularPower = 100.0
+DataRepresentation3.Texture = []
+DataRepresentation3.SelectionCellLabelShadow = 0
+DataRepresentation3.AmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation3.MapScalars = 1
+DataRepresentation3.PointSize = 2.0
+DataRepresentation3.Source.TipLength = 0.35
+DataRepresentation3.SelectionCellLabelFormat = ''
+DataRepresentation3.Scaling = 0
+DataRepresentation3.StaticMode = 0
+DataRepresentation3.SelectionCellLabelColor = [0.0, 1.0, 0.0]
+DataRepresentation3.Source.TipRadius = 0.1
+DataRepresentation3.EdgeColor = [0.0, 0.0, 0.5000076295109483]
+DataRepresentation3.CubeAxesXAxisTickVisibility = 1
+DataRepresentation3.SelectionCellLabelVisibility = 0
+DataRepresentation3.NonlinearSubdivisionLevel = 1
+DataRepresentation3.CubeAxesXAxisRange = [0.0, 1.0]
+DataRepresentation3.Representation = 'Surface'
+DataRepresentation3.CubeAxesYAxisRange = [0.0, 1.0]
+DataRepresentation3.CustomBounds = [0.0, 1.0, 0.0, 1.0, 0.0, 1.0]
+DataRepresentation3.Orientation = [0.0, 0.0, 0.0]
+DataRepresentation3.CubeAxesEnableCustomAxisRange = 0
+DataRepresentation3.CubeAxesXTitle = 'X-Axis'
+DataRepresentation3.CubeAxesInertia = 1
+DataRepresentation3.BackfaceOpacity = 1.0
+DataRepresentation3.SelectionCellFieldDataArrayName = 'vtkOriginalCellIds'
+DataRepresentation3.SelectionColor = [1.0, 0.0, 1.0]
+DataRepresentation3.Ambient = 0.0
+DataRepresentation3.SelectionPointLabelFontSize = 18
+DataRepresentation3.ScaleFactor = 0.9713980622589589
+DataRepresentation3.BackfaceAmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation3.Source.ShaftRadius = 0.03
+DataRepresentation3.SelectMaskArray = ''
+DataRepresentation3.SelectionLineWidth = 2.0
+DataRepresentation3.CubeAxesZAxisMinorTickVisibility = 1
+DataRepresentation3.CubeAxesXAxisVisibility = 1
+DataRepresentation3.Interpolation = 'Gouraud'
+DataRepresentation3.SelectionCellLabelFontFamily = 'Arial'
+DataRepresentation3.SelectionCellLabelItalic = 0
+DataRepresentation3.CubeAxesYAxisMinorTickVisibility = 1
+DataRepresentation3.CubeAxesZGridLines = 0
+DataRepresentation3.SelectionPointLabelFormat = ''
+DataRepresentation3.SelectionPointLabelOpacity = 1.0
+DataRepresentation3.BackfaceDiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation3.Pickable = 1
+DataRepresentation3.CustomBoundsActive = [0, 0, 0]
+DataRepresentation3.SelectionRepresentation = 'Wireframe'
+DataRepresentation3.SelectionPointLabelBold = 0
+DataRepresentation3.ColorArrayName = 'radius'
+DataRepresentation3.SelectionPointLabelItalic = 0
+DataRepresentation3.AllowSpecularHighlightingWithScalarColoring = 0
+DataRepresentation3.SpecularColor = [1.0, 1.0, 1.0]
+DataRepresentation3.LookupTable = a1_radius_PVLookupTable
+DataRepresentation3.SelectionPointSize = 5.0
+DataRepresentation3.SelectionCellLabelBold = 0
+DataRepresentation3.Orient = 0
+
+SetActiveSource(Clip2)
+DataRepresentation5 = Show()
+DataRepresentation5.CubeAxesZAxisVisibility = 1
+DataRepresentation5.SelectionPointLabelColor = [0.5, 0.5, 0.5]
+DataRepresentation5.SelectionPointFieldDataArrayName = 'radius'
+DataRepresentation5.SuppressLOD = 0
+DataRepresentation5.CubeAxesXGridLines = 0
+DataRepresentation5.CubeAxesYAxisTickVisibility = 1
+DataRepresentation5.CubeAxesColor = [1.0, 1.0, 1.0]
+DataRepresentation5.Position = [0.0, 0.0, 0.0]
+DataRepresentation5.BackfaceRepresentation = 'Follow Frontface'
+DataRepresentation5.SelectionOpacity = 1.0
+DataRepresentation5.SelectionPointLabelShadow = 0
+DataRepresentation5.CubeAxesYGridLines = 0
+DataRepresentation5.CubeAxesZAxisRange = [0.0, 1.0]
+DataRepresentation5.OrientationMode = 'Direction'
+DataRepresentation5.Source.TipResolution = 6
+DataRepresentation5.ScaleMode = 'No Data Scaling Off'
+DataRepresentation5.Diffuse = 1.0
+DataRepresentation5.SelectionUseOutline = 0
+DataRepresentation5.SelectionPointLabelFormat = ''
+DataRepresentation5.CubeAxesZTitle = 'Z-Axis'
+DataRepresentation5.Specular = 0.1
+DataRepresentation5.SelectionVisibility = 1
+DataRepresentation5.InterpolateScalarsBeforeMapping = 1
+DataRepresentation5.CubeAxesZAxisTickVisibility = 1
+DataRepresentation5.Origin = [0.0, 0.0, 0.0]
+DataRepresentation5.CubeAxesVisibility = 0
+DataRepresentation5.Scale = [1.0, 1.0, 1.0]
+DataRepresentation5.SelectionCellLabelJustification = 'Left'
+DataRepresentation5.DiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation5.SelectionCellLabelOpacity = 1.0
+DataRepresentation5.CubeAxesInertia = 1
+DataRepresentation5.Source = "Arrow"
+DataRepresentation5.Source.Invert = 0
+DataRepresentation5.Masking = 0
+DataRepresentation5.Opacity = 1.0
+DataRepresentation5.LineWidth = 1.0
+DataRepresentation5.MeshVisibility = 0
+DataRepresentation5.Visibility = 1
+DataRepresentation5.SelectionCellLabelFontSize = 18
+DataRepresentation5.CubeAxesCornerOffset = 0.0
+DataRepresentation5.SelectionPointLabelJustification = 'Left'
+DataRepresentation5.SelectionPointLabelVisibility = 0
+DataRepresentation5.SelectOrientationVectors = ''
+DataRepresentation5.CubeAxesTickLocation = 'Inside'
+DataRepresentation5.BackfaceDiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation5.CubeAxesYAxisVisibility = 1
+DataRepresentation5.SelectionPointLabelFontFamily = 'Arial'
+DataRepresentation5.Source.ShaftResolution = 6
+DataRepresentation5.CubeAxesFlyMode = 'Closest Triad'
+DataRepresentation5.SelectScaleArray = ''
+DataRepresentation5.CubeAxesYTitle = 'Y-Axis'
+DataRepresentation5.ColorAttributeType = 'POINT_DATA'
+DataRepresentation5.SpecularPower = 100.0
+DataRepresentation5.Texture = []
+DataRepresentation5.SelectionCellLabelShadow = 0
+DataRepresentation5.AmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation5.MapScalars = 1
+DataRepresentation5.PointSize = 2.0
+DataRepresentation5.Source.TipLength = 0.35
+DataRepresentation5.SelectionCellLabelFormat = ''
+DataRepresentation5.Scaling = 0
+DataRepresentation5.StaticMode = 0
+DataRepresentation5.SelectionCellLabelColor = [0.0, 1.0, 0.0]
+DataRepresentation5.Source.TipRadius = 0.1
+DataRepresentation5.EdgeColor = [0.0, 0.0, 0.5000076295109483]
+DataRepresentation5.CubeAxesXAxisTickVisibility = 1
+DataRepresentation5.SelectionCellLabelVisibility = 0
+DataRepresentation5.NonlinearSubdivisionLevel = 1
+DataRepresentation5.CubeAxesXAxisRange = [0.0, 1.0]
+DataRepresentation5.Representation = 'Surface'
+DataRepresentation5.CubeAxesYAxisRange = [0.0, 1.0]
+DataRepresentation5.CustomBounds = [0.0, 1.0, 0.0, 1.0, 0.0, 1.0]
+DataRepresentation5.Orientation = [0.0, 0.0, 0.0]
+DataRepresentation5.CubeAxesEnableCustomAxisRange = 0
+DataRepresentation5.CubeAxesXTitle = 'X-Axis'
+DataRepresentation5.ScalarOpacityUnitDistance = 1.1040324233388048
+DataRepresentation5.BackfaceOpacity = 1.0
+DataRepresentation5.SelectionPointLabelFontSize = 18
+DataRepresentation5.SelectionCellFieldDataArrayName = 'vtkOriginalCellIds'
+DataRepresentation5.SelectionColor = [1.0, 0.0, 1.0]
+DataRepresentation5.Ambient = 0.0
+DataRepresentation5.CubeAxesXAxisMinorTickVisibility = 1
+DataRepresentation5.ScaleFactor = 0.8981979608535767
+DataRepresentation5.BackfaceAmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation5.Source.ShaftRadius = 0.03
+DataRepresentation5.ScalarOpacityFunction = a1_radius_PiecewiseFunction
+DataRepresentation5.SelectMaskArray = ''
+DataRepresentation5.SelectionLineWidth = 2.0
+DataRepresentation5.CubeAxesZAxisMinorTickVisibility = 1
+DataRepresentation5.CubeAxesXAxisVisibility = 1
+DataRepresentation5.Interpolation = 'Gouraud'
+DataRepresentation5.SelectMapper = 'Projected tetra'
+DataRepresentation5.SelectionCellLabelFontFamily = 'Arial'
+DataRepresentation5.SelectionCellLabelItalic = 0
+DataRepresentation5.CubeAxesYAxisMinorTickVisibility = 1
+DataRepresentation5.CubeAxesZGridLines = 0
+DataRepresentation5.ExtractedBlockIndex = 0
+DataRepresentation5.SelectionPointLabelOpacity = 1.0
+DataRepresentation5.Pickable = 1
+DataRepresentation5.CustomBoundsActive = [0, 0, 0]
+DataRepresentation5.SelectionRepresentation = 'Wireframe'
+DataRepresentation5.SelectionPointLabelBold = 0
+DataRepresentation5.ColorArrayName = 'radius'
+DataRepresentation5.SelectionPointLabelItalic = 0
+DataRepresentation5.AllowSpecularHighlightingWithScalarColoring = 0
+DataRepresentation5.SpecularColor = [1.0, 1.0, 1.0]
+DataRepresentation5.LookupTable = a1_radius_PVLookupTable
+DataRepresentation5.SelectionPointSize = 5.0
+DataRepresentation5.SelectionCellLabelBold = 0
+DataRepresentation5.Orient = 0
+
+SetActiveSource(testSection_vtk)
+DataRepresentation7 = Show()
+DataRepresentation7.CubeAxesZAxisVisibility = 1
+DataRepresentation7.SelectionPointLabelColor = [0.5, 0.5, 0.5]
+DataRepresentation7.SelectionPointFieldDataArrayName = 'radius'
+DataRepresentation7.SuppressLOD = 0
+DataRepresentation7.CubeAxesXGridLines = 0
+DataRepresentation7.CubeAxesYAxisTickVisibility = 1
+DataRepresentation7.CubeAxesColor = [1.0, 1.0, 1.0]
+DataRepresentation7.Position = [0.0, 0.0, 0.0]
+DataRepresentation7.BackfaceRepresentation = 'Follow Frontface'
+DataRepresentation7.SelectionOpacity = 1.0
+DataRepresentation7.SelectionPointLabelShadow = 0
+DataRepresentation7.CubeAxesYGridLines = 0
+DataRepresentation7.CubeAxesZAxisRange = [0.0, 1.0]
+DataRepresentation7.OrientationMode = 'Direction'
+DataRepresentation7.Source.TipResolution = 6
+DataRepresentation7.ScaleMode = 'No Data Scaling Off'
+DataRepresentation7.Diffuse = 1.0
+DataRepresentation7.SelectionUseOutline = 0
+DataRepresentation7.CubeAxesZTitle = 'Z-Axis'
+DataRepresentation7.Specular = 0.1
+DataRepresentation7.SelectionVisibility = 1
+DataRepresentation7.InterpolateScalarsBeforeMapping = 1
+DataRepresentation7.CubeAxesZAxisTickVisibility = 1
+DataRepresentation7.Origin = [0.0, 0.0, 0.0]
+DataRepresentation7.CubeAxesVisibility = 0
+DataRepresentation7.Scale = [1.0, 1.0, 1.0]
+DataRepresentation7.SelectionCellLabelJustification = 'Left'
+DataRepresentation7.DiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation7.SelectionCellLabelOpacity = 1.0
+DataRepresentation7.Source = "Arrow"
+DataRepresentation7.Source.Invert = 0
+DataRepresentation7.Masking = 0
+DataRepresentation7.Opacity = 1.0
+DataRepresentation7.LineWidth = 1.0
+DataRepresentation7.MeshVisibility = 0
+DataRepresentation7.Visibility = 1
+DataRepresentation7.SelectionCellLabelFontSize = 18
+DataRepresentation7.CubeAxesCornerOffset = 0.0
+DataRepresentation7.SelectionPointLabelJustification = 'Left'
+DataRepresentation7.SelectionPointLabelVisibility = 0
+DataRepresentation7.SelectOrientationVectors = ''
+DataRepresentation7.CubeAxesTickLocation = 'Inside'
+DataRepresentation7.CubeAxesXAxisMinorTickVisibility = 1
+DataRepresentation7.CubeAxesYAxisVisibility = 1
+DataRepresentation7.SelectionPointLabelFontFamily = 'Arial'
+DataRepresentation7.Source.ShaftResolution = 6
+DataRepresentation7.CubeAxesFlyMode = 'Closest Triad'
+DataRepresentation7.SelectScaleArray = ''
+DataRepresentation7.CubeAxesYTitle = 'Y-Axis'
+DataRepresentation7.ColorAttributeType = 'POINT_DATA'
+DataRepresentation7.SpecularPower = 100.0
+DataRepresentation7.Texture = []
+DataRepresentation7.SelectionCellLabelShadow = 0
+DataRepresentation7.AmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation7.MapScalars = 1
+DataRepresentation7.PointSize = 2.0
+DataRepresentation7.Source.TipLength = 0.35
+DataRepresentation7.SelectionCellLabelFormat = ''
+DataRepresentation7.Scaling = 0
+DataRepresentation7.StaticMode = 0
+DataRepresentation7.SelectionCellLabelColor = [0.0, 1.0, 0.0]
+DataRepresentation7.Source.TipRadius = 0.1
+DataRepresentation7.EdgeColor = [0.0, 0.0, 0.5000076295109483]
+DataRepresentation7.CubeAxesXAxisTickVisibility = 1
+DataRepresentation7.SelectionCellLabelVisibility = 0
+DataRepresentation7.NonlinearSubdivisionLevel = 1
+DataRepresentation7.CubeAxesXAxisRange = [0.0, 1.0]
+DataRepresentation7.Representation = 'Surface'
+DataRepresentation7.CubeAxesYAxisRange = [0.0, 1.0]
+DataRepresentation7.CustomBounds = [0.0, 1.0, 0.0, 1.0, 0.0, 1.0]
+DataRepresentation7.Orientation = [0.0, 0.0, 0.0]
+DataRepresentation7.CubeAxesEnableCustomAxisRange = 0
+DataRepresentation7.CubeAxesXTitle = 'X-Axis'
+DataRepresentation7.CubeAxesInertia = 1
+DataRepresentation7.BackfaceOpacity = 1.0
+DataRepresentation7.SelectionCellFieldDataArrayName = 'vtkOriginalCellIds'
+DataRepresentation7.SelectionColor = [1.0, 0.0, 1.0]
+DataRepresentation7.Ambient = 0.0
+DataRepresentation7.SelectionPointLabelFontSize = 18
+DataRepresentation7.ScaleFactor = 0.73055
+DataRepresentation7.BackfaceAmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation7.Source.ShaftRadius = 0.03
+DataRepresentation7.SelectMaskArray = ''
+DataRepresentation7.SelectionLineWidth = 2.0
+DataRepresentation7.CubeAxesZAxisMinorTickVisibility = 1
+DataRepresentation7.CubeAxesXAxisVisibility = 1
+DataRepresentation7.Interpolation = 'Gouraud'
+DataRepresentation7.SelectionCellLabelFontFamily = 'Arial'
+DataRepresentation7.SelectionCellLabelItalic = 0
+DataRepresentation7.CubeAxesYAxisMinorTickVisibility = 1
+DataRepresentation7.CubeAxesZGridLines = 0
+DataRepresentation7.SelectionPointLabelFormat = ''
+DataRepresentation7.SelectionPointLabelOpacity = 1.0
+DataRepresentation7.BackfaceDiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation7.Pickable = 1
+DataRepresentation7.CustomBoundsActive = [0, 0, 0]
+DataRepresentation7.SelectionRepresentation = 'Wireframe'
+DataRepresentation7.SelectionPointLabelBold = 0
+DataRepresentation7.ColorArrayName = 'radius'
+DataRepresentation7.SelectionPointLabelItalic = 0
+DataRepresentation7.AllowSpecularHighlightingWithScalarColoring = 0
+DataRepresentation7.SpecularColor = [1.0, 1.0, 1.0]
+DataRepresentation7.LookupTable = a1_radius_PVLookupTable
+DataRepresentation7.SelectionPointSize = 5.0
+DataRepresentation7.SelectionCellLabelBold = 0
+DataRepresentation7.Orient = 0
+
+SetActiveSource(Glyph3)
+DataRepresentation8 = Show()
+DataRepresentation8.CubeAxesZAxisVisibility = 1
+DataRepresentation8.SelectionPointLabelColor = [0.5, 0.5, 0.5]
+DataRepresentation8.SelectionPointFieldDataArrayName = 'radius'
+DataRepresentation8.SuppressLOD = 0
+DataRepresentation8.CubeAxesXGridLines = 0
+DataRepresentation8.CubeAxesYAxisTickVisibility = 1
+DataRepresentation8.CubeAxesColor = [1.0, 1.0, 1.0]
+DataRepresentation8.Position = [0.0, 0.0, 0.0]
+DataRepresentation8.BackfaceRepresentation = 'Follow Frontface'
+DataRepresentation8.SelectionOpacity = 1.0
+DataRepresentation8.SelectionPointLabelShadow = 0
+DataRepresentation8.CubeAxesYGridLines = 0
+DataRepresentation8.CubeAxesZAxisRange = [0.0, 1.0]
+DataRepresentation8.OrientationMode = 'Direction'
+DataRepresentation8.Source.TipResolution = 6
+DataRepresentation8.ScaleMode = 'No Data Scaling Off'
+DataRepresentation8.Diffuse = 1.0
+DataRepresentation8.SelectionUseOutline = 0
+DataRepresentation8.CubeAxesZTitle = 'Z-Axis'
+DataRepresentation8.Specular = 0.1
+DataRepresentation8.SelectionVisibility = 1
+DataRepresentation8.InterpolateScalarsBeforeMapping = 1
+DataRepresentation8.CubeAxesZAxisTickVisibility = 1
+DataRepresentation8.Origin = [0.0, 0.0, 0.0]
+DataRepresentation8.CubeAxesVisibility = 0
+DataRepresentation8.Scale = [1.0, 1.0, 1.0]
+DataRepresentation8.SelectionCellLabelJustification = 'Left'
+DataRepresentation8.DiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation8.SelectionCellLabelOpacity = 1.0
+DataRepresentation8.Source = "Arrow"
+DataRepresentation8.Source.Invert = 0
+DataRepresentation8.Masking = 0
+DataRepresentation8.Opacity = 1.0
+DataRepresentation8.LineWidth = 1.0
+DataRepresentation8.MeshVisibility = 0
+DataRepresentation8.Visibility = 1
+DataRepresentation8.SelectionCellLabelFontSize = 18
+DataRepresentation8.CubeAxesCornerOffset = 0.0
+DataRepresentation8.SelectionPointLabelJustification = 'Left'
+DataRepresentation8.SelectionPointLabelVisibility = 0
+DataRepresentation8.SelectOrientationVectors = ''
+DataRepresentation8.CubeAxesTickLocation = 'Inside'
+DataRepresentation8.CubeAxesXAxisMinorTickVisibility = 1
+DataRepresentation8.CubeAxesYAxisVisibility = 1
+DataRepresentation8.SelectionPointLabelFontFamily = 'Arial'
+DataRepresentation8.Source.ShaftResolution = 6
+DataRepresentation8.CubeAxesFlyMode = 'Closest Triad'
+DataRepresentation8.SelectScaleArray = ''
+DataRepresentation8.CubeAxesYTitle = 'Y-Axis'
+DataRepresentation8.ColorAttributeType = 'POINT_DATA'
+DataRepresentation8.SpecularPower = 100.0
+DataRepresentation8.Texture = []
+DataRepresentation8.SelectionCellLabelShadow = 0
+DataRepresentation8.AmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation8.MapScalars = 1
+DataRepresentation8.PointSize = 2.0
+DataRepresentation8.Source.TipLength = 0.35
+DataRepresentation8.SelectionCellLabelFormat = ''
+DataRepresentation8.Scaling = 0
+DataRepresentation8.StaticMode = 0
+DataRepresentation8.SelectionCellLabelColor = [0.0, 1.0, 0.0]
+DataRepresentation8.Source.TipRadius = 0.1
+DataRepresentation8.EdgeColor = [0.0, 0.0, 0.5000076295109483]
+DataRepresentation8.CubeAxesXAxisTickVisibility = 1
+DataRepresentation8.SelectionCellLabelVisibility = 0
+DataRepresentation8.NonlinearSubdivisionLevel = 1
+DataRepresentation8.CubeAxesXAxisRange = [0.0, 1.0]
+DataRepresentation8.Representation = 'Surface'
+DataRepresentation8.CubeAxesYAxisRange = [0.0, 1.0]
+DataRepresentation8.CustomBounds = [0.0, 1.0, 0.0, 1.0, 0.0, 1.0]
+DataRepresentation8.Orientation = [0.0, 0.0, 0.0]
+DataRepresentation8.CubeAxesEnableCustomAxisRange = 0
+DataRepresentation8.CubeAxesXTitle = 'X-Axis'
+DataRepresentation8.CubeAxesInertia = 1
+DataRepresentation8.BackfaceOpacity = 1.0
+DataRepresentation8.SelectionCellFieldDataArrayName = 'vtkOriginalCellIds'
+DataRepresentation8.SelectionColor = [1.0, 0.0, 1.0]
+DataRepresentation8.Ambient = 0.0
+DataRepresentation8.SelectionPointLabelFontSize = 18
+DataRepresentation8.ScaleFactor = 0.8328240185976029
+DataRepresentation8.BackfaceAmbientColor = [1.0, 1.0, 1.0]
+DataRepresentation8.Source.ShaftRadius = 0.03
+DataRepresentation8.SelectMaskArray = ''
+DataRepresentation8.SelectionLineWidth = 2.0
+DataRepresentation8.CubeAxesZAxisMinorTickVisibility = 1
+DataRepresentation8.CubeAxesXAxisVisibility = 1
+DataRepresentation8.Interpolation = 'Gouraud'
+DataRepresentation8.SelectionCellLabelFontFamily = 'Arial'
+DataRepresentation8.SelectionCellLabelItalic = 0
+DataRepresentation8.CubeAxesYAxisMinorTickVisibility = 1
+DataRepresentation8.CubeAxesZGridLines = 0
+DataRepresentation8.SelectionPointLabelFormat = ''
+DataRepresentation8.SelectionPointLabelOpacity = 1.0
+DataRepresentation8.BackfaceDiffuseColor = [1.0, 1.0, 1.0]
+DataRepresentation8.Pickable = 1
+DataRepresentation8.CustomBoundsActive = [0, 0, 0]
+DataRepresentation8.SelectionRepresentation = 'Wireframe'
+DataRepresentation8.SelectionPointLabelBold = 0
+DataRepresentation8.ColorArrayName = 'radiusOrig'
+DataRepresentation8.SelectionPointLabelItalic = 0
+DataRepresentation8.AllowSpecularHighlightingWithScalarColoring = 0
+DataRepresentation8.SpecularColor = [1.0, 1.0, 1.0]
+DataRepresentation8.LookupTable = a1_radiusOrig_PVLookupTable
+DataRepresentation8.SelectionPointSize = 5.0
+DataRepresentation8.SelectionCellLabelBold = 0
+DataRepresentation8.Orient = 0
+
+Render()

=== modified file 'examples/test/periodic-geom-compare.py'
--- examples/test/periodic-geom-compare.py	2013-03-28 11:13:12 +0000
+++ examples/test/periodic-geom-compare.py	2014-01-23 18:08:34 +0000
@@ -1,7 +1,6 @@
 # coding: utf-8
 # 2009 © Václav Šmilauer <eudoxos@xxxxxxxx>
 "Test and demonstrate use of PeriTriaxController."
-from yade import *
 from yade import pack
 O.periodic=True
 O.cell.setBox(.1,.1,.1)

=== modified file 'examples/test/periodic-simple-shear.py'
--- examples/test/periodic-simple-shear.py	2013-03-28 11:13:12 +0000
+++ examples/test/periodic-simple-shear.py	2014-01-23 18:08:34 +0000
@@ -2,7 +2,6 @@
 # 2009 © Václav Šmilauer <eudoxos@xxxxxxxx>
 # 2011 ©Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>
 "Test and demonstrate use of PeriTriaxController."
-from yade import *
 from yade import pack,qt
 
 O.periodic=True

=== modified file 'examples/test/periodic-triax-settingHsize.py'
--- examples/test/periodic-triax-settingHsize.py	2013-03-28 11:13:12 +0000
+++ examples/test/periodic-triax-settingHsize.py	2014-01-23 18:08:34 +0000
@@ -1,8 +1,7 @@
 # coding: utf-8
 # 2011 ©Bruno Chareyre <bruno.chareyre@xxxxxxxxxxx>
 "Demonstrate the compression of a periodic cell with non-trivial initial geometry."
-from yade import *
-from yade import pack,log,qt
+from yade import pack,qt
 O.periodic=True
 
 O.cell.hSize=Matrix3(1.0, -0.15, -0.10,

=== modified file 'examples/test/periodic-triax.py'
--- examples/test/periodic-triax.py	2013-03-28 11:13:12 +0000
+++ examples/test/periodic-triax.py	2014-01-23 18:08:34 +0000
@@ -1,7 +1,6 @@
 # coding: utf-8
 # 2009 © Václav Šmilauer <eudoxos@xxxxxxxx>
 "Test and demonstrate use of PeriTriaxController."
-from yade import *
 from yade import pack,qt
 O.periodic=True
 

=== modified file 'examples/test/unv-read/unvRead.py'
--- examples/test/unv-read/unvRead.py	2012-03-13 15:23:04 +0000
+++ examples/test/unv-read/unvRead.py	2014-01-23 18:08:34 +0000
@@ -1,4 +1,3 @@
-from yade import *
 from yade import ymport
 
 facets = ymport.unv('shell.unv',shift=(100,200,300),scale=1000)

=== modified file 'examples/test/vtk-exporter/vtkExporter.py'
--- examples/test/vtk-exporter/vtkExporter.py	2013-07-10 09:16:15 +0000
+++ examples/test/vtk-exporter/vtkExporter.py	2014-01-28 13:33:10 +0000
@@ -1,5 +1,5 @@
-from yade import *
-from yade import export
+from yade import export,polyhedra_utils
+mat = PolyhedraMat()
 
 O.bodies.append([
 	sphere((0,0,0),1),
@@ -7,8 +7,14 @@
 	sphere((0,2,4),2),
 	sphere((0,5,2),1.5),
 	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)])
+	facet([Vector3(0,-3,-1),Vector3(0,-2,5),Vector3(-5,4,0)]),
+	polyhedra_utils.polyhedra(mat,(1,2,3),0),
+	polyhedra_utils.polyhedralBall(2,20,mat,(-2,-2,4)),
 ])
+O.bodies[-1].state.pos = (-2,-2,-2)
+O.bodies[-1].state.ori = Quaternion((1,1,2),1)
+O.bodies[-2].state.pos = (-2,-2,3)
+O.bodies[-2].state.ori = Quaternion((1,2,0),1)
 
 createInteraction(0,1)
 createInteraction(0,2)
@@ -17,7 +23,10 @@
 createInteraction(1,3)
 createInteraction(2,3)
 
+O.step()
+
 vtkExporter = export.VTKExporter('vtkExporterTesting')
 vtkExporter.exportSpheres(what=[('dist','b.state.pos.norm()')])
 vtkExporter.exportFacets(what=[('pos','b.state.pos')])
 vtkExporter.exportInteractions(what=[('kn','i.phys.kn')])
+vtkExporter.exportPolyhedra(what=[('n','b.id')])

=== modified file 'examples/tetra/oneTetra.py'
--- examples/tetra/oneTetra.py	2013-10-15 17:11:37 +0000
+++ examples/tetra/oneTetra.py	2013-12-10 13:50:46 +0000
@@ -8,7 +8,7 @@
 v3 = (0,1,0)
 v4 = (0,0,1)
 
-t1 = tetraOld((v1,v2,v3,v4),color=(0,1,0))
+t1 = tetra((v1,v2,v3,v4),color=(0,1,0))
 O.bodies.append((t1))
 
 def changeVelocity():

=== modified file 'examples/timeStepperUsage.py'
--- examples/timeStepperUsage.py	2013-05-14 21:24:11 +0000
+++ examples/timeStepperUsage.py	2014-01-23 18:08:34 +0000
@@ -1,7 +1,7 @@
 # coding: utf-8
 # 2012 © Bruno Chareyre <bruno.chareyre_A_hmg.inpg.fr>
 "Test and demonstrate the use of timestepper and density scaling."
-from yade import *
+
 from yade import pack,qt,timing
 O.periodic=True
 

=== modified file 'examples/triax-tutorial/script-session1.py'
--- examples/triax-tutorial/script-session1.py	2013-07-16 09:57:52 +0000
+++ examples/triax-tutorial/script-session1.py	2014-01-03 20:43:21 +0000
@@ -35,6 +35,7 @@
 from yade.params import table
 
 num_spheres=table.num_spheres# number of spheres
+key=table.key
 targetPorosity = 0.43 #the porosity we want for the packing
 compFricDegree = table.compFricDegree # initial contact friction during the confining phase (will be decreased during the REFD compaction process)
 finalFricDegree = 30 # contact friction during the deviatoric loading

=== modified file 'gui/qt4/GLViewer.cpp'
--- gui/qt4/GLViewer.cpp	2013-10-14 20:51:11 +0000
+++ gui/qt4/GLViewer.cpp	2014-02-16 14:03:41 +0000
@@ -35,7 +35,6 @@
 	#include<gl2ps.h>
 #endif
 
-static int last(-1);
 static unsigned initBlocked(State::DOF_NONE);
 
 CREATE_LOGGER(GLViewer);
@@ -65,7 +64,7 @@
 	cut_plane_delta = -2;
 	gridSubdivide = false;
 	resize(550,550);
-
+	last=-1;
 	if(viewId==0) setWindowTitle("Primary view");
 	else setWindowTitle(("Secondary view #"+lexical_cast<string>(viewId)).c_str());
 
@@ -87,6 +86,7 @@
 	setKeyDescription(Qt::Key_D,"Toggle time display mask");
 	setKeyDescription(Qt::Key_G,"Toggle grid visibility; g turns on and cycles");
 	setKeyDescription(Qt::Key_G & Qt::ShiftModifier ,"Hide grid.");
+	setKeyDescription(Qt::Key_M, "Move selected object.");
 	setKeyDescription(Qt::Key_X,"Show the xz [shift: xy] (up-right) plane (clip plane: align normal with +x)");
 	setKeyDescription(Qt::Key_Y,"Show the yx [shift: yz] (up-right) plane (clip plane: align normal with +y)");
 	setKeyDescription(Qt::Key_Z,"Show the zy [shift: zx] (up-right) plane (clip plane: align normal with +z)");
@@ -224,8 +224,18 @@
 	else if(e->key()==Qt::Key_D) {timeDispMask+=1; if(timeDispMask>(TIME_REAL|TIME_VIRT|TIME_ITER))timeDispMask=0; }
 	else if(e->key()==Qt::Key_G) { if(e->modifiers() & Qt::ShiftModifier){ drawGrid=0; return; } else drawGrid++; if(drawGrid>=8) drawGrid=0; }
 	else if (e->key()==Qt::Key_M && selectedName() >= 0){ 
-		if(!(isMoving=!isMoving)){displayMessage("Moving done."); if (last>=0) {Body::byId(Body::id_t(last))->state->blockedDOFs=initBlocked; last=-1; Omega::instance().getScene()->selectedBody = -1;} mouseMovesCamera();}
-		else{ displayMessage("Moving selected object"); mouseMovesManipulatedFrame();}
+		if(!(isMoving=!isMoving)){
+			displayMessage("Moving done.");
+			if (last>=0) {Body::byId(Body::id_t(last))->state->blockedDOFs=initBlocked; last=-1;} mouseMovesCamera();}
+		else{ 	displayMessage("Moving selected object");
+			
+			long selection = Omega::instance().getScene()->selectedBody;
+			initBlocked=Body::byId(Body::id_t(selection))->state->blockedDOFs; last=selection;
+			Body::byId(Body::id_t(selection))->state->blockedDOFs=State::DOF_ALL;
+			Quaternionr& q = Body::byId(selection)->state->ori;
+			Vector3r&    v = Body::byId(selection)->state->pos;
+			manipulatedFrame()->setPositionAndOrientation(qglviewer::Vec(v[0],v[1],v[2]),qglviewer::Quaternion(q.x(),q.y(),q.z(),q.w()));
+			mouseMovesManipulatedFrame();}
 	}
 	else if (e->key() == Qt::Key_T) camera()->setType(camera()->type()==qglviewer::Camera::ORTHOGRAPHIC ? qglviewer::Camera::PERSPECTIVE : qglviewer::Camera::ORTHOGRAPHIC);
 	else if(e->key()==Qt::Key_O) camera()->setFieldOfView(camera()->fieldOfView()*0.9);
@@ -393,19 +403,15 @@
 	}
 	if(selection>=0 && (*(Omega::instance().getScene()->bodies)).exists(selection)){
 		resetManipulation();
+		if (last>=0) {Body::byId(Body::id_t(last))->state->blockedDOFs=initBlocked; last=-1;}
 		if(Body::byId(Body::id_t(selection))->isClumpMember()){ // select clump (invisible) instead of its member
 			LOG_DEBUG("Clump member #"<<selection<<" selected, selecting clump instead.");
 			selection=Body::byId(Body::id_t(selection))->clumpId;			
 		}
-		initBlocked=Body::byId(Body::id_t(selection))->state->blockedDOFs;
-		Body::byId(Body::id_t(selection))->state->blockedDOFs=State::DOF_ALL;
 		
 		setSelectedName(selection);
 		LOG_DEBUG("New selection "<<selection);
 		displayMessage("Selected body #"+lexical_cast<string>(selection)+(Body::byId(selection)->isClump()?" (clump)":""));
-		Quaternionr& q = Body::byId(selection)->state->ori;
-		Vector3r&    v = Body::byId(selection)->state->pos;
-		manipulatedFrame()->setPositionAndOrientation(qglviewer::Vec(v[0],v[1],v[2]),qglviewer::Quaternion(q.x(),q.y(),q.z(),q.w()));
 		Omega::instance().getScene()->selectedBody = selection;
 			PyGILState_STATE gstate;
 			gstate = PyGILState_Ensure();

=== modified file 'gui/qt4/GLViewer.hpp'
--- gui/qt4/GLViewer.hpp	2013-03-14 20:01:49 +0000
+++ gui/qt4/GLViewer.hpp	2014-02-16 14:03:41 +0000
@@ -49,6 +49,7 @@
 		float			cut_plane;
 		int			cut_plane_delta;
 		bool			gridSubdivide;
+		long			last;
 		int manipulatedClipPlane;
 		set<int> boundClipPlanes;
 		shared_ptr<qglviewer::LocalConstraint> xyPlaneConstraint;

=== modified file 'gui/qt4/GLViewerDisplay.cpp'
--- gui/qt4/GLViewerDisplay.cpp	2013-10-16 05:48:14 +0000
+++ gui/qt4/GLViewerDisplay.cpp	2014-02-16 14:03:41 +0000
@@ -89,7 +89,6 @@
 		int selection = selectedName();
 		if(selection!=-1 && (*(Omega::instance().getScene()->bodies)).exists(selection) && isMoving){
 			static Real lastTimeMoved(0);
-			static Real initv0(0); static Real initv1(0); static Real initv2(0);
 			float v0,v1,v2; manipulatedFrame()->getPosition(v0,v1,v2);
 			if(last == selection) // delay by one redraw, so the body will not jump into 0,0,0 coords
 			{
@@ -98,22 +97,13 @@
 				Vector3r&    vel = (*(Omega::instance().getScene()->bodies))[selection]->state->vel;
 				Vector3r&    angVel = (*(Omega::instance().getScene()->bodies))[selection]->state->angVel;
 				angVel=Vector3r::Zero(); 
-				if (!initv0 && !initv1 && !initv2){initv0=v0;initv1=v1;initv2=v2;}
-				if (initv0!=v0 || initv1!=v1 || initv2!=v2) {
-					Real dt=(scene->time-lastTimeMoved); lastTimeMoved=scene->time;
-					if (dt!=0) { 
-						vel[0]=-(v[0]-v0)/dt; vel[1]=-(v[1]-v1)/dt; vel[2]=-(v[2]-v2)/dt;
-						vel[0]=-(initv0-v0)/dt; vel[1]=-(initv1-v1)/dt; vel[2]=-(initv2-v2)/dt;
-						initv0=v0;initv1=v1;initv2=v2;
-					}
-				}
-				else {vel[0]=vel[1]=vel[2]=0; /*v[0]=v0;v[1]=v1;v[2]=v2;*/}
-				v[0]=v0;v[1]=v1;v[2]=v2;
+				Real dt=(scene->time-lastTimeMoved); lastTimeMoved=scene->time;
+				if (dt!=0) { vel[0]=-(v[0]-v0)/dt; vel[1]=-(v[1]-v1)/dt; vel[2]=-(v[2]-v2)/dt;}
+				else vel[0]=vel[1]=vel[2]=0;
 				//FIXME: should update spin like velocity above, when the body is rotated:
 				double q0,q1,q2,q3; manipulatedFrame()->getOrientation(q0,q1,q2,q3);	q.x()=q0;q.y()=q1;q.z()=q2;q.w()=q3;
 			}
 			(*(Omega::instance().getScene()->bodies))[selection]->userForcedDisplacementRedrawHook();	
-			last=selection;
 		}
 		if(manipulatedClipPlane>=0){
 			assert(manipulatedClipPlane<renderer->numClipPlanes);

=== modified file 'gui/qt4/GLViewerMouse.cpp'
--- gui/qt4/GLViewerMouse.cpp	2013-10-16 05:48:14 +0000
+++ gui/qt4/GLViewerMouse.cpp	2014-01-06 13:57:32 +0000
@@ -36,20 +36,34 @@
 #endif
 
 void GLViewer::mouseMovesCamera(){
-	camera()->frame()->setWheelSensitivity(-1.0f);
-
-	setMouseBinding(Qt::SHIFT + Qt::LeftButton, SELECT);
-	//setMouseBinding(Qt::RightButton, NO_CLICK_ACTION);
-	setMouseBinding(Qt::SHIFT + Qt::LeftButton + Qt::RightButton, FRAME, ZOOM);
-	setMouseBinding(Qt::SHIFT + Qt::MidButton, FRAME, TRANSLATE);
-	setMouseBinding(Qt::SHIFT + Qt::RightButton, FRAME, ROTATE);
-	setWheelBinding(Qt::ShiftModifier , FRAME, ZOOM);
-
-	setMouseBinding(Qt::LeftButton + Qt::RightButton, CAMERA, ZOOM);
-	setMouseBinding(Qt::MidButton, CAMERA, ZOOM);
-	setMouseBinding(Qt::LeftButton, CAMERA, ROTATE);
-	setMouseBinding(Qt::RightButton, CAMERA, TRANSLATE);
-	setWheelBinding(Qt::NoModifier, CAMERA, ZOOM);
+  camera()->frame()->setWheelSensitivity(-1.0f);
+  
+  setWheelBinding(Qt::ShiftModifier , FRAME, ZOOM);
+  setWheelBinding(Qt::NoModifier, CAMERA, ZOOM);
+
+#if QGLVIEWER_VERSION>=0x020500
+  setMouseBinding(Qt::ShiftModifier, Qt::LeftButton, SELECT);
+  
+  setMouseBinding(Qt::ShiftModifier, Qt::LeftButton | Qt::RightButton, FRAME, ZOOM);
+  setMouseBinding(Qt::ShiftModifier, Qt::MidButton, FRAME, TRANSLATE);
+  setMouseBinding(Qt::ShiftModifier, Qt::RightButton, FRAME, ROTATE);
+    
+  setMouseBinding(Qt::NoModifier, Qt::RightButton, CAMERA, ZOOM);
+  setMouseBinding(Qt::NoModifier, Qt::MidButton, CAMERA, ZOOM);
+  setMouseBinding(Qt::NoModifier, Qt::LeftButton, CAMERA, ROTATE);
+  setMouseBinding(Qt::NoModifier, Qt::RightButton, CAMERA, TRANSLATE);
+#else
+  setMouseBinding(Qt::SHIFT + Qt::LeftButton, SELECT);
+  
+  setMouseBinding(Qt::SHIFT + Qt::LeftButton + Qt::RightButton, FRAME, ZOOM);
+  setMouseBinding(Qt::SHIFT + Qt::MidButton, FRAME, TRANSLATE);
+  setMouseBinding(Qt::SHIFT + Qt::RightButton, FRAME, ROTATE);
+  
+  setMouseBinding(Qt::LeftButton + Qt::RightButton, CAMERA, ZOOM);
+  setMouseBinding(Qt::MidButton, CAMERA, ZOOM);
+  setMouseBinding(Qt::LeftButton, CAMERA, ROTATE);
+  setMouseBinding(Qt::RightButton, CAMERA, TRANSLATE);
+#endif
 };
 
 void GLViewer::mouseMovesManipulatedFrame(qglviewer::Constraint* c){

=== modified file 'gui/qt4/__init__.py'
--- gui/qt4/__init__.py	2013-11-06 15:33:02 +0000
+++ gui/qt4/__init__.py	2013-12-04 21:49:34 +0000
@@ -22,13 +22,13 @@
 "Number of webkit windows that will be cycled to show help on clickable objects"
 webWindows=[] 
 "holds instances of QtWebKit windows; clicking an url will open it in the window that was the least recently updated"
-sphinxOnlineDocPath='https://www.yade-dem.org/sphinx/'
+sphinxOnlineDocPath='https://www.yade-dem.org/doc/'
 "Base URL for the documentation. Packaged versions should change to the local installation directory."
 
 
 import os.path
 # find if we have docs installed locally from package
-sphinxLocalDocPath=yade.config.prefix+'/share/doc/yade'+yade.config.suffix+'/html/'
+sphinxLocalDocPath=yade.config.prefix+'/share/doc/yade'+yade.config.suffix+'-doc/html/'
 sphinxBuildDocPath=yade.config.sourceRoot+'/doc/sphinx/_build/html/'
 # we prefer the packaged documentation for this version, if installed
 if   os.path.exists(sphinxLocalDocPath+'/index.html'): sphinxPrefix='file://'+sphinxLocalDocPath

=== modified file 'lib/triangulation/FlowBoundingSphere.hpp'
--- lib/triangulation/FlowBoundingSphere.hpp	2014-01-29 17:06:48 +0000
+++ lib/triangulation/FlowBoundingSphere.hpp	2014-02-17 18:00:12 +0000
@@ -115,7 +115,7 @@
 		void ComputeTetrahedralForces();
 		/// Define forces spliting drag and buoyancy terms
 		void ComputeFacetForcesWithCache(bool onlyCache=false);
-		void saveVtk ( );
+		void saveVtk (const char* folder);
 #ifdef XVIEW
 		void Dessine_Triangulation ( Vue3D &Vue, RTriangulation &T );
 		void Dessine_Short_Tesselation ( Vue3D &Vue, Tesselation &Tes );

=== modified file 'lib/triangulation/FlowBoundingSphere.ipp'
--- lib/triangulation/FlowBoundingSphere.ipp	2014-01-29 17:06:48 +0000
+++ lib/triangulation/FlowBoundingSphere.ipp	2014-02-17 18:00:12 +0000
@@ -101,7 +101,7 @@
 }
 
 template <class Tesselation> 
-void FlowBoundingSphere<Tesselation>::ResetNetwork() {noCache=true;}
+void FlowBoundingSphere<Tesselation>::ResetNetwork() {T[0].Clear();noCache=true;}
 
 template <class Tesselation> 
 Tesselation& FlowBoundingSphere<Tesselation>::Compute_Action()
@@ -418,7 +418,7 @@
 	if (noCache) {cerr<<"Triangulation does not exist. Waht did you do?!"<<endl; return -1;}
 	RTriangulation& Tri = T[noCache?(!currentTes):currentTes].Triangulation();
 	Cell_handle cell = Tri.locate(Point(X,Y,Z));
-	return cell->info().index;
+	return cell->info().id;
 }
 
 template <class Tesselation> 
@@ -487,7 +487,6 @@
 void FlowBoundingSphere<Tesselation>::ComputeFacetForcesWithCache(bool onlyCache)
 {
 	RTriangulation& Tri = T[currentTes].Triangulation();
-	Finite_cells_iterator cell_end = Tri.finite_cells_end();
 	Vecteur nullVect(0,0,0);
 	//reset forces
 	if (!onlyCache) for (Finite_vertices_iterator v = Tri.finite_vertices_begin(); v != Tri.finite_vertices_end(); ++v) v->info().forces=nullVect;
@@ -497,10 +496,9 @@
 		perVertexUnitForce.clear(); perVertexPressure.clear();
 // 		vector<const Vecteur*> exf; exf.reserve(20);
 // 		vector<const Real*> exp; exp.reserve(20);
-		perVertexUnitForce.resize(Tri.number_of_vertices());
-		perVertexPressure.resize(Tri.number_of_vertices());}
+		perVertexUnitForce.resize(T[currentTes].max_id+1);
+		perVertexPressure.resize(T[currentTes].max_id+1);}
 	#endif
-
 	Cell_handle neighbour_cell;
 	Vertex_handle mirror_vertex;
 	Vecteur tempVect;
@@ -560,6 +558,7 @@
 		#else
 		#pragma omp parallel for num_threads(ompThreads)
 		for (int vn=0; vn<= T[currentTes].max_id; vn++) {
+			if (T[currentTes].vertexHandles[vn]==NULL) continue;
 			Vertex_handle& v = T[currentTes].vertexHandles[vn];
 // 		for (Finite_vertices_iterator v = Tri.finite_vertices_begin(); v != Tri.finite_vertices_end(); ++v){
 			const int& id =  v->info().id();
@@ -1322,13 +1321,13 @@
 	num_particles = real;
 }
 template <class Tesselation> 
-void FlowBoundingSphere<Tesselation>::saveVtk()
+void FlowBoundingSphere<Tesselation>::saveVtk(const char* folder)
 {
 	RTriangulation& Tri = T[noCache?(!currentTes):currentTes].Triangulation();
         static unsigned int number = 0;
         char filename[80];
-	mkdir("./VTK", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
-        sprintf(filename,"./VTK/out_%d.vtk", number++);
+	mkdir(folder, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+        sprintf(filename,"%s/out_%d.vtk",folder,number++);
 	int firstReal=-1;
 
 	//count fictious vertices and cells

=== modified file 'lib/triangulation/FlowBoundingSphereLinSolv.ipp'
--- lib/triangulation/FlowBoundingSphereLinSolv.ipp	2013-06-27 11:29:17 +0000
+++ lib/triangulation/FlowBoundingSphereLinSolv.ipp	2013-11-26 15:37:26 +0000
@@ -161,7 +161,8 @@
 		for (Finite_cells_iterator cell = Tri.finite_cells_begin(); cell != cell_end; cell++) {
 			orderedCells.push_back(cell);
 			if (!cell->info().Pcondition) ++ncols;}
-		spatial_sort(orderedCells.begin(),orderedCells.end(), CellTraits_for_spatial_sort<RTriangulation>());
+//		//Segfault on 14.10, and useless overall since SuiteSparse has preconditionners (including metis)
+// 		spatial_sort(orderedCells.begin(),orderedCells.end(), CellTraits_for_spatial_sort<RTriangulation>());
 
 		T_cells.clear();
 		T_index=0;

=== modified file 'lib/triangulation/PeriodicFlow.cpp'
--- lib/triangulation/PeriodicFlow.cpp	2013-05-03 16:45:52 +0000
+++ lib/triangulation/PeriodicFlow.cpp	2013-11-21 01:28:17 +0000
@@ -47,7 +47,6 @@
 void PeriodicFlow::ComputeFacetForcesWithCache(bool onlyCache)
 {
 	RTriangulation& Tri = T[currentTes].Triangulation();
-	Finite_cells_iterator cell_end = Tri.finite_cells_end();
 	Vecteur nullVect(0,0,0);
 	static vector<Vecteur> oldForces;
 	if (oldForces.size()<=Tri.number_of_vertices()) oldForces.resize(Tri.number_of_vertices()+1);

=== modified file 'lib/triangulation/def_types.h'
--- lib/triangulation/def_types.h	2014-02-06 18:48:43 +0000
+++ lib/triangulation/def_types.h	2014-02-17 18:00:12 +0000
@@ -44,6 +44,9 @@
 
 class SimpleCellInfo : public Point {
 	public:
+	//"id": unique identifier of each cell, independant of other numberings used in the fluid types.
+	// Care to initialize it, there is no magic numbering to rely on
+	unsigned int id;
 	Real s;
 	bool isFictious;
 	SimpleCellInfo (void) {isFictious=false; s=0;}

=== modified file 'pkg/common/Cylinder.cpp'
--- pkg/common/Cylinder.cpp	2013-08-23 15:21:20 +0000
+++ pkg/common/Cylinder.cpp	2014-02-03 11:21:42 +0000
@@ -741,13 +741,13 @@
 
     if (currentContactPhysics->fragile && (-Fn)> currentContactPhysics->normalAdhesion) {
         // BREAK due to tension
-        scene->interactions->requestErase(contact->getId1(),contact->getId2());
+        scene->interactions->requestErase(contact);
     } else {
         if ((-Fn)> currentContactPhysics->normalAdhesion) {//normal plasticity
             Fn=-currentContactPhysics->normalAdhesion;
             currentContactPhysics->unp = un+currentContactPhysics->normalAdhesion/currentContactPhysics->kn;
             if (currentContactPhysics->unpMax && currentContactPhysics->unp<currentContactPhysics->unpMax)
-                scene->interactions->requestErase(contact->getId1(),contact->getId2());
+                scene->interactions->requestErase(contact);
         }
         currentContactPhysics->normalForce = Fn*geom->normal;
         Vector3r& shearForce = geom->rotate(currentContactPhysics->shearForce);
@@ -823,13 +823,13 @@
     
     if (currentContactPhysics->fragile && (-Fn)> currentContactPhysics->normalAdhesion) {
         // BREAK due to tension
-        scene->interactions->requestErase(contact->getId1(),contact->getId2());
+        scene->interactions->requestErase(contact);
     } else {
         if ((-Fn)> currentContactPhysics->normalAdhesion) {//normal plasticity
             Fn=-currentContactPhysics->normalAdhesion;
             currentContactPhysics->unp = un+currentContactPhysics->normalAdhesion/currentContactPhysics->kn;
             if (currentContactPhysics->unpMax && currentContactPhysics->unp<currentContactPhysics->unpMax)
-                scene->interactions->requestErase(contact->getId1(),contact->getId2());
+                scene->interactions->requestErase(contact);
         }
     
         

=== modified file 'pkg/common/Dispatching.cpp'
--- pkg/common/Dispatching.cpp	2012-01-30 20:53:49 +0000
+++ pkg/common/Dispatching.cpp	2014-02-03 11:21:42 +0000
@@ -93,11 +93,6 @@
 }
 
 void IGeomDispatcher::action(){
-	// Erase interaction that were requested for erase, but not processed by the collider, if any (and warn once about that, as it is suspicious)
-	if(scene->interactions->unconditionalErasePending()>0 && !alreadyWarnedNoCollider){
-		LOG_WARN("Interactions pending erase found, no collider being used?");
-		alreadyWarnedNoCollider=true;
-	}
 	updateScenePtr();
 
 	shared_ptr<BodyContainer>& bodies = scene->bodies;

=== modified file 'pkg/common/Grid.cpp'
--- pkg/common/Grid.cpp	2013-11-12 08:29:26 +0000
+++ pkg/common/Grid.cpp	2014-02-12 13:18:59 +0000
@@ -219,8 +219,14 @@
 				// ... and check whether the sphere projection is before the neighbours connections too.
 				const shared_ptr<Interaction> intr = scene->interactions->find(c->id1,gridNo1->ConnList[i]->getId());
 				if(relPosPrev<=0){ //if the sphere projection is outside both the current Connection AND this neighbouring connection, then create the interaction if the neighbour did not already do it before.
-					if(intr && intr->isReal() && isNew) return false;
-					if(intr && intr->isReal() && !isNew) {scm->isDuplicate=1;/*cout<<"Declare "<<c->id1<<"-"<<c->id2<<" as duplicated."<<endl;*/}
+					const shared_ptr<Interaction> intr = scene->interactions->find(c->id1,gridNo1->ConnList[i]->getId());
+					if(intr && intr->isReal()){
+						shared_ptr<ScGridCoGeom> intrGeom=YADE_PTR_CAST<ScGridCoGeom>(intr->geom);
+						if(!intrGeom->isDuplicate==1){ //skip contact.
+							if (isNew) {return false;}
+							else {scm->isDuplicate=1;}/*cout<<"Declare "<<c->id1<<"-"<<c->id2<<" as duplicated."<<endl;*/
+						}
+					}
 				}
 				else{//the sphere projection is outside the current Connection but inside the previous neighbour. The contact has to be handled by the Prev GridConnection, not here.
 					if (isNew)return false;
@@ -247,10 +253,15 @@
 					if(abs(segtNext[j])<1e-14) segtNext[j]=0.0;
 				}
 				Real relPosNext = (branchN.dot(segtNext))/(segtNext.norm()*segtNext.norm());
-				const shared_ptr<Interaction> intr = scene->interactions->find(c->id1,gridNo2->ConnList[i]->getId());
 				if(relPosNext<=0){ //if the sphere projection is outside both the current Connection AND this neighbouring connection, then create the interaction if the neighbour did not already do it before.
-					if(intr && intr->isReal() && isNew) return false;
-					if(intr && intr->isReal() && !isNew) {scm->isDuplicate=1;/*cout<<"Declare "<<c->id1<<"-"<<c->id2<<" as duplicated."<<endl;*/}
+					const shared_ptr<Interaction> intr = scene->interactions->find(c->id1,gridNo2->ConnList[i]->getId());
+					if(intr && intr->isReal()){
+						shared_ptr<ScGridCoGeom> intrGeom=YADE_PTR_CAST<ScGridCoGeom>(intr->geom);
+						if(!intrGeom->isDuplicate==1){
+							if (isNew) return false;
+							else scm->isDuplicate=1;/*cout<<"Declare "<<c->id1<<"-"<<c->id2<<" as duplicated."<<endl;*/
+						}
+					}
 				}
 				else{//the sphere projection is outside the current Connection but inside the previous neighbour. The contact has to be handled by the Prev GridConnection, not here.
 					if (isNew)return false;

=== modified file 'pkg/common/InsertionSortCollider.cpp'
--- pkg/common/InsertionSortCollider.cpp	2013-05-30 20:20:59 +0000
+++ pkg/common/InsertionSortCollider.cpp	2014-02-02 20:49:51 +0000
@@ -264,7 +264,7 @@
 					for(long j=i+1; /* handle case 2. of swapped min/max */ j<2*nBodies && V[j].id!=iid; j++){
 						const Body::id_t& jid=V[j].id;
 						// take 2 of the same condition (only handle collision [min_i..max_i]+min_j, not [min_i..max_i]+min_i (symmetric)
-						if(!V[j].flags.isMin) continue;
+						if(!(V[j].flags.isMin && V[j].flags.hasBB)) continue;
 						/* abuse the same function here; since it does spatial overlap check first, it is OK to use it */
 						handleBoundInversion(iid,jid,interactions,scene);
 						assert(j<2*nBodies-1);
@@ -278,7 +278,7 @@
 					// we might wrap over the periodic boundary here; that's why the condition is different from the aperiodic case
 					for(long j=V.norm(i+1); V[j].id!=iid; j=V.norm(j+1)){
 						const Body::id_t& jid=V[j].id;
-						if(!V[j].flags.isMin) continue;
+						if(!(V[j].flags.isMin && V[j].flags.hasBB)) continue;
 						handleBoundInversionPeri(iid,jid,interactions,scene);
 						if(cnt++>2*(long)nBodies){ LOG_FATAL("Uninterrupted loop in the initial sort?"); throw std::logic_error("loop??"); }
 					}

=== modified file 'pkg/common/InsertionSortCollider.hpp'
--- pkg/common/InsertionSortCollider.hpp	2012-09-08 01:19:45 +0000
+++ pkg/common/InsertionSortCollider.hpp	2014-02-17 14:31:35 +0000
@@ -82,7 +82,14 @@
 
 class NewtonIntegrator;
 
+class Integrator;
+
+class GeneralIntegratorInsertionSortCollider;// Forward decleration of child to decleare it as friend
+
 class InsertionSortCollider: public Collider{
+
+	friend GeneralIntegratorInsertionSortCollider;
+
 	//! struct for storing bounds of bodies
 	struct Bounds{
 		//! coordinate along the given sortAxis

=== modified file 'pkg/common/InteractionLoop.cpp'
--- pkg/common/InteractionLoop.cpp	2013-04-23 14:07:34 +0000
+++ pkg/common/InteractionLoop.cpp	2014-02-03 11:21:42 +0000
@@ -21,10 +21,10 @@
 
 
 void InteractionLoop::action(){
-	if(eraseIntsInLoop && scene->interactions->unconditionalErasePending()>0 && !alreadyWarnedNoCollider){
-		LOG_WARN("Interactions pending erase found (erased), no collider being used?");
-		alreadyWarnedNoCollider=true;
-	}
+// 	if(eraseIntsInLoop && scene->interactions->conditionalyEraseNonReal(scene)>0 && !alreadyWarnedNoCollider){
+// 		LOG_WARN("Interactions pending erase found (erased), no collider being used?");
+// 		alreadyWarnedNoCollider=true;
+// 	}
 	/*
 	if(scene->interactions->dirty){
 		throw std::logic_error("InteractionContainer::dirty is true; the collider should re-initialize in such case and clear the dirty flag.");

=== modified file 'pkg/common/OpenGLRenderer.cpp'
--- pkg/common/OpenGLRenderer.cpp	2013-05-30 20:13:27 +0000
+++ pkg/common/OpenGLRenderer.cpp	2014-02-16 16:42:06 +0000
@@ -85,7 +85,9 @@
 
 
 void OpenGLRenderer::setBodiesDispInfo(){
-	if(scene->bodies->size()!=bodyDisp.size()) bodyDisp.resize(scene->bodies->size());
+	if(scene->bodies->size()!=bodyDisp.size()) {
+		bodyDisp.resize(scene->bodies->size());
+		for (Body::id_t k=0; k<scene->bodies->size(); k++) bodyDisp[k].hidden=0;}
 	bool scaleRotations=(rotScale!=1.0);
 	bool scaleDisplacements=(dispScale!=Vector3r::Ones());
 	FOREACH(const shared_ptr<Body>& b, *scene->bodies){
@@ -305,7 +307,7 @@
 
 	FOREACH(const shared_ptr<Body>& b, *scene->bodies){
 		if(!b || !b->bound) continue;
-		if(!bodyDisp[b->getId()].isDisplayed) continue;
+		if(!bodyDisp[b->getId()].isDisplayed or bodyDisp[b->getId()].hidden) continue;
 		if(b->bound && ((b->getGroupMask()&mask) || b->getGroupMask()==0)){
 			glPushMatrix(); boundDispatcher(b->bound,scene.get()); glPopMatrix();
 		}
@@ -339,7 +341,7 @@
 	// but it is still better than crashes if the body gets deleted meanwile.
 	FOREACH(shared_ptr<Body> b, *scene->bodies){
 		if(!b || !b->shape) continue;
-		if(!bodyDisp[b->getId()].isDisplayed) continue;
+		if(!(bodyDisp[b->getId()].isDisplayed and !bodyDisp[b->getId()].hidden)) continue;
 		Vector3r pos=bodyDisp[b->getId()].pos;
 		Quaternionr ori=bodyDisp[b->getId()].ori;
 		if(!b->shape || !((b->getGroupMask()&mask) || b->getGroupMask()==0)) continue;

=== modified file 'pkg/common/OpenGLRenderer.hpp'
--- pkg/common/OpenGLRenderer.hpp	2013-05-30 20:13:27 +0000
+++ pkg/common/OpenGLRenderer.hpp	2014-02-16 16:42:06 +0000
@@ -44,9 +44,12 @@
 			Vector3r pos;
 			Quaternionr ori;
 			bool isDisplayed;
+			bool hidden;
 		};
 		//! display data for individual bodies
 		vector<BodyDisp> bodyDisp;
+		void hide(Body::id_t id) {if ((unsigned int) id<bodyDisp.size()) bodyDisp[id].hidden=true; }
+		void show(Body::id_t id) {if ((unsigned int) id<bodyDisp.size()) bodyDisp[id].hidden=false; }
 
 		virtual ~OpenGLRenderer();
 
@@ -119,6 +122,8 @@
 		/*py*/
 		.def("setRefSe3",&OpenGLRenderer::setBodiesRefSe3,"Make current positions and orientation reference for scaleDisplacements and scaleRotations.")
 		.def("render",&OpenGLRenderer::pyRender,"Render the scene in the current OpenGL context.")
+		.def("hideBody",&OpenGLRenderer::hide,(python::arg("id")),"Hide body from id (see :yref:`OpenGLRenderer::showBody`)")
+		.def("showBody",&OpenGLRenderer::show,(python::arg("id")),"Make body visible (see :yref:`OpenGLRenderer::hideBody`)")
 	);
 };
 REGISTER_SERIALIZABLE(OpenGLRenderer);

=== modified file 'pkg/common/SpatialQuickSortCollider.cpp'
--- pkg/common/SpatialQuickSortCollider.cpp	2012-02-29 19:07:56 +0000
+++ pkg/common/SpatialQuickSortCollider.cpp	2014-02-03 11:21:42 +0000
@@ -26,7 +26,7 @@
 
 	// This collider traverses all interactions at every step, therefore all interactions
 	// that were requested for erase might be erased here and will be recreated if necessary.
-	scene->interactions->unconditionalErasePending();
+	scene->interactions->eraseNonReal();
 
 	size_t nbElements=bodies->size();
 	if (nbElements!=rank.size())

=== modified file 'pkg/common/Wall.cpp'
--- pkg/common/Wall.cpp	2010-11-12 08:03:16 +0000
+++ pkg/common/Wall.cpp	2014-01-13 09:23:51 +0000
@@ -39,6 +39,7 @@
 		a1[ax0]=b1[ax0]=a2[ax0]=b2[ax0]=0;
 		a1[ax1]=mn1-step; a2[ax2]=mn2-step;
 		b1[ax1]=mn1+step*(div+2); b2[ax2]=mn2+step*(div+2);
+		glColor3v(cm->color);
 		glBegin(GL_LINES);
 			for(int i=0; i<=div; i++){
 				a1[ax2]=b1[ax2]=mn1+i*step;

=== modified file 'pkg/dem/CohFrictPhys.hpp'
--- pkg/dem/CohFrictPhys.hpp	2012-10-09 09:09:02 +0000
+++ pkg/dem/CohFrictPhys.hpp	2014-01-21 15:08:51 +0000
@@ -19,17 +19,17 @@
 
 	YADE_CLASS_BASE_DOC_ATTRS_CTOR(CohFrictPhys,FrictPhys,"",
 		((bool,cohesionDisablesFriction,false,,"is shear strength the sum of friction and adhesion or only adhesion?"))
-		((bool,cohesionBroken,true,,"is cohesion active? will be set false when a fragile contact is broken"))
+		((bool,cohesionBroken,true,,"is cohesion active? Set to false at the creation of a cohesive contact, and set to true when a fragile contact is broken"))
 		((bool,fragile,true,,"do cohesion disapear when contact strength is exceeded?"))
 		((Real,kr,0,,"rotational stiffness [N.m/rad]"))
 		((Real,ktw,0,,"twist stiffness [N.m/rad]"))
 		((Real,maxRollPl,0.0,,"Coefficient to determine the maximum plastic rolling moment."))
 		((Vector3r,maxTwistMoment,Vector3r::Zero(),,"Maximum elastic value for the twisting moment (if zero, plasticity will not be applied). In CohFrictMat a parameter should be added to decide what value should be attributed to this threshold value."))
 		((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."))
-		((Real,unpMax,0,,"maximum value of plastic normal displacement, after that the interaction breaks even if :yref:`CohFrictPhys::fragile`=false. The default value (0) means no maximum."))
-		((bool,momentRotationLaw,false,,"use bending/twisting moment at contacts. See :yref:`CohFrictPhys::cohesionDisablesFriction` for details."))
+		((Real,shearAdhesion,0,,"cohesive part of the shear strength (a frictional term might be added depending on :yref:`CohFrictPhys::cohesionDisablesFriction`)"))
+		((Real,unp,0,,"plastic normal displacement, only used for tensile behaviour and if :yref:`CohFrictPhys::fragile` =false."))
+		((Real,unpMax,0,,"maximum value of plastic normal displacement, after that the interaction breaks even if :yref:`CohFrictPhys::fragile` =false. The default value (0) means no maximum."))
+		((bool,momentRotationLaw,false,,"use bending/twisting moment at contacts. See :yref:`Law2_ScGeom6D_CohFrictPhys_CohesionMoment::always_use_moment_law` for details."))
 		((bool,initCohesion,false,,"Initialize the cohesive behaviour with current state as equilibrium state (same as :yref:`Ip2_CohFrictMat_CohFrictMat_CohFrictPhys::setCohesionNow` but acting on only one interaction)"))
 		((Real,creep_viscosity,-1,,"creep viscosity [Pa.s/m]."))
 		// internal attributes

=== modified file 'pkg/dem/CohesiveFrictionalContactLaw.hpp'
--- pkg/dem/CohesiveFrictionalContactLaw.hpp	2013-05-29 09:48:51 +0000
+++ pkg/dem/CohesiveFrictionalContactLaw.hpp	2014-01-21 15:06:34 +0000
@@ -20,7 +20,7 @@
 		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_CohFrictPhys_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$.",
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGeom6D_CohFrictPhys_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_s$ 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`."))

=== modified file 'pkg/dem/FlatGridCollider.cpp'
--- pkg/dem/FlatGridCollider.cpp	2010-11-07 11:46:20 +0000
+++ pkg/dem/FlatGridCollider.cpp	2014-02-03 11:21:42 +0000
@@ -11,7 +11,7 @@
 
 bool FlatGridCollider::isActivated(){
 	// keep interactions trequested for deletion as potential (forget removal requests)
-	scene->interactions->clearPendingErase();
+// 	scene->interactions->clearPendingErase();
 	if(!newton) return true;
 	// handle verlet distance
 	fastestBodyMaxDist+=sqrt(newton->maxVelocitySq)*scene->dt;

=== modified file 'pkg/dem/FlowEngine.cpp'
--- pkg/dem/FlowEngine.cpp	2014-01-29 17:06:48 +0000
+++ pkg/dem/FlowEngine.cpp	2014-02-17 18:00:12 +0000
@@ -64,15 +64,9 @@
         timingDeltas->checkpoint ( "Update_Volumes" );
 	
         Eps_Vol_Cumulative += eps_vol_max;
-        if ( (defTolerance>0 && Eps_Vol_Cumulative > defTolerance) || retriangulationLastIter>meshUpdateInterval) {
-                updateTriangulation = true;
-                Eps_Vol_Cumulative=0;
-                retriangulationLastIter=0;
-                ReTrg++;
-        } else  {
-		updateTriangulation = false;
-		retriangulationLastIter++;}
-
+	retriangulationLastIter++;
+	if (!updateTriangulation) updateTriangulation = // If not already set true by another function of by the user, check conditions
+		(defTolerance>0 && Eps_Vol_Cumulative > defTolerance) || retriangulationLastIter>meshUpdateInterval;
 
         ///Compute flow and and forces here
 	if (pressureForce){
@@ -119,6 +113,7 @@
 			backgroundCompleted=false;
 			retriangulationLastIter=ellapsedIter;
 			updateTriangulation=false;
+			Eps_Vol_Cumulative=0;
 			ellapsedIter=0;
 			boost::thread workerThread(&FlowEngine::backgroundAction,this);
 			workerThread.detach();
@@ -136,7 +131,10 @@
 			Build_Triangulation (P_zero, solver);
 			Initialize_volumes(solver);
 			ComputeViscousForces(*solver);
-               		updateTriangulation = false;}
+               		updateTriangulation = false;
+			Eps_Vol_Cumulative=0;
+			retriangulationLastIter=0;
+			ReTrg++;}
         }
         first=false;
         timingDeltas->checkpoint ( "Triangulate + init volumes" );
@@ -267,8 +265,10 @@
 	flow->T[flow->currentTes].cellHandles.clear();
 	flow->T[flow->currentTes].cellHandles.reserve(flow->T[flow->currentTes].Triangulation().number_of_finite_cells());
 	Finite_cells_iterator cell_end = flow->T[flow->currentTes].Triangulation().finite_cells_end();
-	for ( Finite_cells_iterator cell = flow->T[flow->currentTes].Triangulation().finite_cells_begin(); cell != cell_end; cell++ )
+	int k=0;
+	for ( Finite_cells_iterator cell = flow->T[flow->currentTes].Triangulation().finite_cells_begin(); cell != cell_end; cell++ ){
 		flow->T[flow->currentTes].cellHandles.push_back(cell);
+		cell->info().id=k++;}//define unique numbering now, corresponds to position in cellHandles
         flow->DisplayStatistics ();
         flow->Compute_Permeability();
         porosity = flow->V_porale_porosity/flow->V_totale_porosity;
@@ -732,14 +732,10 @@
 	timingDeltas->checkpoint("Triangulating");
         UpdateVolumes (solver);
         Eps_Vol_Cumulative += eps_vol_max;
-        if ( (defTolerance>0 && Eps_Vol_Cumulative > defTolerance) || retriangulationLastIter>meshUpdateInterval ) {
-                updateTriangulation = true;
-                Eps_Vol_Cumulative=0;
-                retriangulationLastIter=0;
-                ReTrg++;
-         } else  {
-		updateTriangulation = false;
-		retriangulationLastIter++;}
+	retriangulationLastIter++;
+	if (!updateTriangulation) updateTriangulation = // If not already set true by another function of by the user, check conditions
+		(defTolerance>0 && Eps_Vol_Cumulative > defTolerance) || retriangulationLastIter>meshUpdateInterval;
+
 	timingDeltas->checkpoint("Update_Volumes");
 
 	///Compute flow and and forces here
@@ -784,6 +780,7 @@
 			backgroundCompleted=false;
 			retriangulationLastIter=ellapsedIter;
 			ellapsedIter=0;
+			Eps_Vol_Cumulative=0;
 			boost::thread workerThread(&PeriodicFlowEngine::backgroundAction,this);
 			workerThread.detach();
 			Initialize_volumes(solver);
@@ -798,7 +795,10 @@
 			Build_Triangulation (P_zero, solver);
 			Initialize_volumes(solver);
 			ComputeViscousForces(*solver);
-               		updateTriangulation = false;}
+               		updateTriangulation = false;
+			Eps_Vol_Cumulative=0;
+                	retriangulationLastIter=0;
+                	ReTrg++;}
         }
         first=false;
 	timingDeltas->checkpoint("Ending");

=== modified file 'pkg/dem/FlowEngine.hpp'
--- pkg/dem/FlowEngine.hpp	2013-10-25 07:27:55 +0000
+++ pkg/dem/FlowEngine.hpp	2014-02-03 16:10:48 +0000
@@ -139,13 +139,20 @@
 		Real Volume_cell (Cellhandle cell);
 		void Oedometer_Boundary_Conditions();
 		void Average_real_cell_velocity();
-		void saveVtk() {solver->saveVtk();}
+		void saveVtk(const char* folder) {solver->saveVtk(folder);}
 		vector<Real> avFlVelOnSph(unsigned int id_sph) {return solver->Average_Fluid_Velocity_On_Sphere(id_sph);}
 
 // 		void setBoundaryVel(Vector3r vel) {topBoundaryVelocity=vel; updateTriangulation=true;}
 		void pressureProfile(double wallUpY, double wallDownY) {return solver->measurePressureProfile(wallUpY,wallDownY);}
 		double getPorePressure(Vector3r pos){return solver->getPorePressure(pos[0], pos[1], pos[2]);}
 		TPL int getCell(double posX, double posY, double posZ, Solver& flow){return flow->getCell(posX, posY, posZ);}
+		TPL unsigned int nCells(Solver& flow){return flow->T[flow->currentTes].cellHandles.size();}
+		TPL python::list getVertices(unsigned int id, Solver& flow){
+			python::list ids;
+			if (id>=flow->T[flow->currentTes].cellHandles.size()) {LOG_ERROR("id out of range, max value is "<<flow->T[flow->currentTes].cellHandles.size()); return ids;}			
+			for (unsigned int i=0;i<4;i++) ids.append(flow->T[flow->currentTes].cellHandles[id]->vertex(i)->info().id());
+			return ids;
+		}
 		double averageSlicePressure(double posY){return solver->averageSlicePressure(posY);}
 		double averagePressure(){return solver->averagePressure();}
 		#ifdef LINSOLV
@@ -181,6 +188,8 @@
 		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);}
+		unsigned int	_nCells() {return nCells(solver);}
+		python::list	_getVertices(unsigned int id) {return getVertices(id,solver);}
 		#ifdef LINSOLV
 		void 		_exportMatrix(string filename) {exportMatrix(filename,solver);}
 		void 		_exportTriplets(string filename) {exportTriplets(filename,solver);}
@@ -267,7 +276,6 @@
 					normal[wall_ymax].y()=normal[wall_xmax].x()=normal[wall_zmax].z()=-1;
 					solver = shared_ptr<FlowSolver> (new FlowSolver);
 					first=true;
-					updateTriangulation=false;
 					eps_vol_max=Eps_Vol_Cumulative=retriangulationLastIter=0;
 					ReTrg=1;
 					backgroundCompleted=true;
@@ -282,7 +290,7 @@
 					.def("getBoundaryFlux",&FlowEngine::_getBoundaryFlux,(python::arg("boundary")),"Get total flux through boundary defined by its body id.\n\n.. note:: The flux may be not zero even for no-flow condition. This artifact comes from cells which are incident to two or more boundaries (along the edges of the sample, typically). Such flux evaluation on impermeable boundary is just irrelevant, it does not imply that the boundary condition is not applied properly.")
 					.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("saveVtk",&FlowEngine::saveVtk,(python::arg("folder")="./VTK"),"Save pressure field in vtk format. Specify a folder name for output.")
 					.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.")
 					.def("shearLubForce",&FlowEngine::_shearLubForce,(python::arg("Id_sph")),"Return the shear lubrication force on sphere Id_sph.")
@@ -304,6 +312,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 an engine outside the timestepping loop).")
 					.def("getCell",&FlowEngine::_getCell,(python::arg("pos")),"get id of the cell containing (X,Y,Z).")
+					.def("nCells",&FlowEngine::_nCells,"get the total number of finite cells in the triangulation.")
+					.def("getVertices",&FlowEngine::_getVertices,(python::arg("id")),"get the vertices of a cell")
 					#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.")
@@ -371,7 +381,7 @@
 		void preparePShifts();
 		
 		//(re)instanciation of templates and others, for python binding
-		void saveVtk() {solver->saveVtk();}
+		void saveVtk(const char* folder) {solver->saveVtk(folder);}
 		Vector3r 	_shearLubForce(unsigned int id_sph) {return shearLubForce(id_sph,solver);}
 		Vector3r 	_shearLubTorque(unsigned int id_sph) {return shearLubTorque(id_sph,solver);}
 		Vector3r 	_normalLubForce(unsigned int id_sph) {return normalLubForce(id_sph,solver);}
@@ -426,7 +436,6 @@
 			wallIds=vector<int>(6,-1);
 // 			wallTopId=wallBottomId=wallFrontId=wallBackId=wallLeftId=wallRightId=-1;
 			solver = shared_ptr<FlowSolver> (new FlowSolver);
-			updateTriangulation=false;
 			eps_vol_max=Eps_Vol_Cumulative=retriangulationLastIter=0;
 			ReTrg=1;
 			first=true;
@@ -449,7 +458,7 @@
 			.def("OSI",&PeriodicFlowEngine::_OSI,"Return the number of interactions only between spheres.")
 
 // 			.def("imposeFlux",&FlowEngine::_imposeFlux,(python::arg("pos"),python::arg("p")),"Impose incoming flux in boundary cell of location 'pos'.")
-			.def("saveVtk",&PeriodicFlowEngine::saveVtk,"Save pressure field in vtk format.")
+			.def("saveVtk",&PeriodicFlowEngine::saveVtk,(python::arg("folder")="./VTK"),"Save pressure field in vtk format. Specify a folder name for output.")
 			.def("imposePressure",&PeriodicFlowEngine::_imposePressure,(python::arg("pos"),python::arg("p")),"Impose pressure in cell of location 'pos'. The index of the condition is returned (for multiple imposed pressures at different points).")
 			.def("getBoundaryFlux",&PeriodicFlowEngine::_getBoundaryFlux,(python::arg("boundary")),"Get total flux through boundary defined by its body id.")
 			.def("getPorePressure",&PeriodicFlowEngine::getPorePressure,(python::arg("pos")),"Measure pore pressure in position pos[0],pos[1],pos[2]")

=== added file 'pkg/dem/FrictViscoPM.cpp'
--- pkg/dem/FrictViscoPM.cpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/FrictViscoPM.cpp	2014-01-24 21:59:41 +0000
@@ -0,0 +1,228 @@
+/*************************************************************************
+*  Copyright (C) 2014 by Klaus Thoeni                                    *
+*  klaus.thoeni@xxxxxxxxxxxxxxxx                                         *
+*                                                                        *
+*  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. *
+*************************************************************************/
+
+#include"FrictViscoPM.hpp"
+#include<yade/pkg/dem/ScGeom.hpp>
+#include<yade/core/Omega.hpp>
+#include<yade/core/Scene.hpp>
+
+YADE_PLUGIN((FrictViscoMat)(FrictViscoPhys)(Ip2_FrictViscoMat_FrictViscoMat_FrictViscoPhys)(Ip2_FrictMat_FrictViscoMat_FrictViscoPhys)(Law2_ScGeom_FrictViscoPhys_CundallStrackVisco));
+
+FrictViscoMat::~FrictViscoMat(){}
+
+/********************** Ip2_FrictViscoMat_FrictMat_FrictViscoPhys ****************************/
+CREATE_LOGGER(FrictViscoPhys);
+
+FrictViscoPhys::~FrictViscoPhys(){};
+
+/********************** Ip2_FrictViscoMat_FrictMat_FrictViscoPhys ****************************/
+CREATE_LOGGER(Ip2_FrictViscoMat_FrictViscoMat_FrictViscoPhys);
+
+void Ip2_FrictViscoMat_FrictViscoMat_FrictViscoPhys::go(const shared_ptr<Material>& b1, const shared_ptr<Material>& b2, const shared_ptr<Interaction>& interaction){
+
+	LOG_TRACE( "Ip2_FrictViscoMat_FrictViscoMat_FrictViscoPhys::go - contact law" );
+
+	if(interaction->phys) return;
+	const shared_ptr<FrictViscoMat>& mat1 = YADE_PTR_CAST<FrictViscoMat>(b1);
+	const shared_ptr<FrictViscoMat>& mat2 = YADE_PTR_CAST<FrictViscoMat>(b2);
+	interaction->phys = shared_ptr<FrictViscoPhys>(new FrictViscoPhys());
+	const shared_ptr<FrictViscoPhys>& contactPhysics = YADE_PTR_CAST<FrictViscoPhys>(interaction->phys);
+	Real Ea 	= mat1->young;
+	Real Eb 	= mat2->young;
+	Real Va 	= mat1->poisson;
+	Real Vb 	= mat2->poisson;
+
+	Real Ra,Rb;
+	assert(dynamic_cast<GenericSpheresContact*>(interaction->geom.get()));//only in debug mode
+	GenericSpheresContact* sphCont=YADE_CAST<GenericSpheresContact*>(interaction->geom.get());
+	Ra=sphCont->refR1>0?sphCont->refR1:sphCont->refR2;
+	Rb=sphCont->refR2>0?sphCont->refR2:sphCont->refR1;
+	
+	// calculate stiffness from MatchMaker or use harmonic avarage as usual if not given
+	Real Kn = (kn) ? (*kn)(mat1->id,mat2->id) : 2.*Ea*Ra*Eb*Rb/(Ea*Ra+Eb*Rb);
+	Real Ks = (kRatio) ? (*kRatio)(mat1->id,mat2->id)*Kn : 2.*Ea*Ra*Va*Eb*Rb*Vb/(Ea*Ra*Va+Eb*Rb*Vb);
+	
+	Real frictionAngle = (!frictAngle) ? std::min(mat1->frictionAngle,mat2->frictionAngle) : (*frictAngle)(mat1->id,mat2->id,mat1->frictionAngle,mat2->frictionAngle);
+	contactPhysics->tangensOfFrictionAngle = std::tan(frictionAngle);
+	contactPhysics->kn = Kn;
+	contactPhysics->ks = Ks;
+
+	/************************/
+	/* DAMPING COEFFICIENTS */
+	/************************/
+	Real betana = mat1->betan;
+	Real betanb = mat2->betan;
+	
+	// inclusion of local viscous damping
+	if (betana!=0 || betanb!=0){
+		Body::id_t ida = interaction->getId1(); // get id body 1
+		Body::id_t idb = interaction->getId2(); // get id body 2
+		State* dea = Body::byId(ida,scene)->state.get();
+		State* deb = Body::byId(idb,scene)->state.get();
+		const shared_ptr<Body>& ba=Body::byId(ida,scene); 
+		const shared_ptr<Body>& bb=Body::byId(idb,scene);
+		Real mbar = (!ba->isDynamic() && bb->isDynamic()) ? deb->mass : ((!bb->isDynamic() && ba->isDynamic()) ? dea->mass : (dea->mass*deb->mass / (dea->mass + deb->mass))); // get equivalent mass if both bodies are dynamic, if not set it equal to the one of the dynamic body
+		TRVAR2(Kn,mbar);
+		contactPhysics->cn_crit = 2.*sqrt(mbar*Kn); // Critical damping coefficient (normal direction)
+		contactPhysics->cn = contactPhysics->cn_crit * ( (betana!=0 && betanb!=0) ? ((betana+betanb)/2.) : ( (betanb==0) ? betana : betanb )); // Damping normal coefficient
+	}
+	else
+		contactPhysics->cn=0.;
+	TRVAR1(contactPhysics->cn);
+
+}
+
+/********************** Ip2_FrictViscoMat_FrictMat_FrictViscoPhys ****************************/
+CREATE_LOGGER(Ip2_FrictMat_FrictViscoMat_FrictViscoPhys);
+
+void Ip2_FrictMat_FrictViscoMat_FrictViscoPhys::go(const shared_ptr<Material>& b1, const shared_ptr<Material>& b2, const shared_ptr<Interaction>& interaction){
+
+	LOG_TRACE( "Ip2_FrictMat_FrictViscoMat_FrictViscoPhys::go - contact law" );
+
+	if(interaction->phys) return;
+	const shared_ptr<FrictMat>& mat1 = YADE_PTR_CAST<FrictMat>(b1);
+	const shared_ptr<FrictViscoMat>& mat2 = YADE_PTR_CAST<FrictViscoMat>(b2);
+	interaction->phys = shared_ptr<FrictViscoPhys>(new FrictViscoPhys());
+	const shared_ptr<FrictViscoPhys>& contactPhysics = YADE_PTR_CAST<FrictViscoPhys>(interaction->phys);
+	Real Ea 	= mat1->young;
+	Real Eb 	= mat2->young;
+	Real Va 	= mat1->poisson;
+	Real Vb 	= mat2->poisson;
+
+	Real Ra,Rb;
+	assert(dynamic_cast<GenericSpheresContact*>(interaction->geom.get()));//only in debug mode
+	GenericSpheresContact* sphCont=YADE_CAST<GenericSpheresContact*>(interaction->geom.get());
+	Ra=sphCont->refR1>0?sphCont->refR1:sphCont->refR2;
+	Rb=sphCont->refR2>0?sphCont->refR2:sphCont->refR1;
+	
+	// calculate stiffness from MatchMaker or use harmonic avarage as usual if not given
+	Real Kn = (kn) ? (*kn)(mat1->id,mat2->id) : 2.*Ea*Ra*Eb*Rb/(Ea*Ra+Eb*Rb);
+	Real Ks = (kRatio) ? (*kRatio)(mat1->id,mat2->id)*Kn : 2.*Ea*Ra*Va*Eb*Rb*Vb/(Ea*Ra*Va+Eb*Rb*Vb);
+	
+	Real frictionAngle = (!frictAngle) ? std::min(mat1->frictionAngle,mat2->frictionAngle) : (*frictAngle)(mat1->id,mat2->id,mat1->frictionAngle,mat2->frictionAngle);
+	contactPhysics->tangensOfFrictionAngle = std::tan(frictionAngle);
+	contactPhysics->kn = Kn;
+	contactPhysics->ks = Ks;
+
+	/************************/
+	/* DAMPING COEFFICIENTS */
+	/************************/
+	Real betanb = mat2->betan;
+	
+	// inclusion of local viscous damping
+	if (betanb!=0){
+		Body::id_t ida = interaction->getId1(); // get id body 1
+		Body::id_t idb = interaction->getId2(); // get id body 2
+		State* dea = Body::byId(ida,scene)->state.get();
+		State* deb = Body::byId(idb,scene)->state.get();
+		const shared_ptr<Body>& ba=Body::byId(ida,scene); 
+		const shared_ptr<Body>& bb=Body::byId(idb,scene);
+		Real mbar = (!ba->isDynamic() && bb->isDynamic()) ? deb->mass : ((!bb->isDynamic() && ba->isDynamic()) ? dea->mass : (dea->mass*deb->mass / (dea->mass + deb->mass))); // get equivalent mass if both bodies are dynamic, if not set it equal to the one of the dynamic body
+		TRVAR2(Kn,mbar);
+		contactPhysics->cn_crit = 2.*sqrt(mbar*Kn); // Critical damping coefficient (normal direction)
+		contactPhysics->cn = contactPhysics->cn_crit * betanb; // Damping normal coefficient
+	}
+	else
+		contactPhysics->cn=0.;
+	TRVAR1(contactPhysics->cn);
+
+}
+
+/********************** Law2_ScGeom_FrictViscoPhys_CundallStrackVisco ****************************/
+
+// #if 1
+Real Law2_ScGeom_FrictViscoPhys_CundallStrackVisco::getPlasticDissipation() {return (Real) plasticDissipation;}
+void Law2_ScGeom_FrictViscoPhys_CundallStrackVisco::initPlasticDissipation(Real initVal) {plasticDissipation.reset(); plasticDissipation+=initVal;}
+Real Law2_ScGeom_FrictViscoPhys_CundallStrackVisco::elasticEnergy()
+{
+	Real energy=0;
+	FOREACH(const shared_ptr<Interaction>& I, *scene->interactions){
+		if(!I->isReal()) continue;
+		FrictPhys* phys = dynamic_cast<FrictPhys*>(I->phys.get());
+		if(phys) {
+			energy += 0.5*(phys->normalForce.squaredNorm()/phys->kn + phys->shearForce.squaredNorm()/phys->ks);}
+	}
+	return energy;
+}
+// #endif
+
+
+CREATE_LOGGER(Law2_ScGeom_FrictViscoPhys_CundallStrackVisco);
+
+void Law2_ScGeom_FrictViscoPhys_CundallStrackVisco::go(shared_ptr<IGeom>& ig, shared_ptr<IPhys>& ip, Interaction* contact)
+{
+	LOG_TRACE( "Law2_ScGeom_FrictViscoPhys_CundallStrackVisco::go - create interaction physics" );
+
+	int id1 = contact->getId1(), id2 = contact->getId2();
+
+	ScGeom*    geom= static_cast<ScGeom*>(ig.get());
+	FrictViscoPhys* phys = static_cast<FrictViscoPhys*>(ip.get());
+	if(geom->penetrationDepth <0){
+		if (neverErase) {
+			phys->shearForce = Vector3r::Zero();
+			phys->normalForce = Vector3r::Zero();}
+		else 	scene->interactions->requestErase(contact);
+		return;
+	}
+	Real& un=geom->penetrationDepth;
+	phys->normalForce = phys->kn*std::max(un,(Real) 0) * geom->normal;
+	
+	/************************/
+	/* DAMPING CONTRIBUTION */
+	/************************/
+	
+	// define shifts to handle periodicity
+	const Vector3r shift2 = scene->isPeriodic ? scene->cell->intrShiftPos(contact->cellDist): Vector3r::Zero(); 
+	const Vector3r shiftVel = scene->isPeriodic ? scene->cell->intrShiftVel(contact->cellDist): Vector3r::Zero(); 
+
+	State* de1 = Body::byId(id1,scene)->state.get();
+	State* de2 = Body::byId(id2,scene)->state.get();
+	
+	// get incident velocity
+	Vector3r incidentV = geom->getIncidentVel(de1, de2, scene->dt, shift2, shiftVel);	
+	Vector3r incidentVn = geom->normal.dot(incidentV)*geom->normal; // contact normal velocity
+	phys->normalViscous = phys->cn*incidentVn;
+	phys->normalForce -= phys->normalViscous;
+	
+	// shear force
+	Vector3r& shearForce = geom->rotate(phys->shearForce);
+	const Vector3r& shearDisp = geom->shearIncrement();
+	shearForce -= phys->ks*shearDisp;
+	Real maxFs = phys->normalForce.squaredNorm()*std::pow(phys->tangensOfFrictionAngle,2);
+
+	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();
+			shearForce *= ratio;}
+	} else {
+		//almost the same with additional Vector3r instatinated for energy tracing, 
+		//duplicated block to make sure there is no cost for the instanciation of the vector when traceEnergy==false
+		if(shearForce.squaredNorm() > maxFs){
+			Real ratio = sqrt(maxFs) / shearForce.norm();
+			Vector3r trialForce=shearForce;//store prev force for definition of plastic slip
+			//define the plastic work input and increment the total plastic energy dissipated
+			shearForce *= ratio;
+			Real dissip=((1/phys->ks)*(trialForce-shearForce))/*plastic disp*/ .dot(shearForce)/*active force*/;
+			if (traceEnergy) plasticDissipation += dissip;
+			else if(dissip>0) scene->energy->add(dissip,"plastDissip",plastDissipIx,/*reset*/false);
+		}
+		// 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 && !sphericalBodies) {
+		applyForceAtContactPoint(-phys->normalForce-shearForce, geom->contactPoint, id1, de1->se3.position, id2, de2->se3.position);}
+	else {//we need to use correct branches in the periodic case, the following apply for spheres only
+		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));
+	}
+}
+

=== added file 'pkg/dem/FrictViscoPM.hpp'
--- pkg/dem/FrictViscoPM.hpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/FrictViscoPM.hpp	2014-01-24 21:59:41 +0000
@@ -0,0 +1,120 @@
+/*************************************************************************
+*  Copyright (C) 2014 by Klaus Thoeni                                    *
+*  klaus.thoeni@xxxxxxxxxxxxxxxx                                         *
+*                                                                        *
+*  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. *
+*************************************************************************/
+
+/**
+=== OVERVIEW OF FrictViscoPM ===
+
+A particle model for friction and viscous damping in normal direction. The damping coefficient
+has to be defined with the material whereas the contact stiffness kn and ks/kn can be defined with the Ip2 functor.
+
+Remarks:
+- maybe there is a better way of implementing this without copying from ElasticContactLaw
+- maybe we can combine some ideas of this contact law with other contact laws
+*/
+
+#pragma once
+
+#include<yade/pkg/common/ElastMat.hpp>
+#include<yade/pkg/common/Dispatching.hpp>
+#include<yade/pkg/common/MatchMaker.hpp>
+#include<yade/pkg/dem/FrictPhys.hpp>
+#include<yade/pkg/dem/ScGeom.hpp>
+#include<yade/lib/base/openmp-accu.hpp>
+
+#include<set>
+#include<boost/tuple/tuple.hpp>
+
+/** This class holds information associated with each body */
+class FrictViscoMat: public FrictMat {
+	public:
+		virtual ~FrictViscoMat();
+		YADE_CLASS_BASE_DOC_ATTRS_CTOR(FrictViscoMat,FrictMat,"Material for use with the FrictViscoPM classes",
+			((Real,betan,0.,,"Fraction of the viscous damping coefficient in normal direction equal to $\\frac{c_{n}}{C_{n,crit}}$."))
+			,
+			createIndex();
+		);
+		DECLARE_LOGGER;
+		REGISTER_CLASS_INDEX(FrictViscoMat,FrictMat);
+};
+REGISTER_SERIALIZABLE(FrictViscoMat);
+
+
+/** This class holds information associated with each interaction */
+class FrictViscoPhys: public FrictPhys {
+	public:
+		virtual ~FrictViscoPhys();
+		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(FrictViscoPhys,FrictPhys,"Representation of a single interaction of the FrictViscoPM type, storage for relevant parameters",
+			((Real,cn_crit,NaN,,"Normal viscous constant for ctitical damping defined as $\\c_{n}=C_{n,crit}\\beta_n$."))
+			((Real,cn,NaN,,"Normal viscous constant defined as $\\c_{n}=c_{n,crit}\\beta_n$."))
+			((Vector3r,normalViscous,Vector3r::Zero(),,"Normal viscous component"))
+			,
+			createIndex();
+			,
+		);
+		DECLARE_LOGGER;
+		REGISTER_CLASS_INDEX(FrictViscoPhys,FrictPhys);
+};
+REGISTER_SERIALIZABLE(FrictViscoPhys);
+
+/** 2d functor creating IPhys (Ip2) taking FrictViscoMat and FrictViscoMat of 2 bodies, returning type FrictViscoPhys */
+class Ip2_FrictViscoMat_FrictViscoMat_FrictViscoPhys: public IPhysFunctor{
+	public:
+		virtual void go(const shared_ptr<Material>& pp1, const shared_ptr<Material>& pp2, const shared_ptr<Interaction>& interaction);
+		
+		FUNCTOR2D(FrictViscoMat,FrictViscoMat);
+		
+		YADE_CLASS_BASE_DOC_ATTRS(Ip2_FrictViscoMat_FrictViscoMat_FrictViscoPhys,IPhysFunctor,"Converts 2 :yref:`FrictViscoMat` instances to :yref:`FrictViscoPhys` with corresponding parameters. Basically this functor corresponds to :yref:`Ip2_FrictMat_FrictMat_FrictPhys` with the only difference that damping in normal direction can be considered.",
+		((shared_ptr<MatchMaker>,kn,,,"Instance of :yref:`MatchMaker` determining how to compute interaction's normal contact stiffnesses. If this value is not given the elastic properties (i.e. young) of the two colliding materials are used to calculate the stiffness."))
+		((shared_ptr<MatchMaker>,kRatio,,,"Instance of :yref:`MatchMaker` determining how to compute interaction's shear contact stiffnesses. If this value is not given the elastic properties (i.e. poisson) of the two colliding materials are used to calculate the stiffness."))
+		((shared_ptr<MatchMaker>,frictAngle,,,"Instance of :yref:`MatchMaker` determining how to compute interaction's friction angle. If ``None``, minimum value is used."))
+		);
+		DECLARE_LOGGER;
+};
+REGISTER_SERIALIZABLE(Ip2_FrictViscoMat_FrictViscoMat_FrictViscoPhys);
+
+/** 2d functor creating IPhys (Ip2) taking FrictMat and FrictViscoMat of 2 bodies, returning type FrictViscoPhys */
+class Ip2_FrictMat_FrictViscoMat_FrictViscoPhys: public IPhysFunctor{
+	public:
+		virtual void go(const shared_ptr<Material>& pp1, const shared_ptr<Material>& pp2, const shared_ptr<Interaction>& interaction);
+		
+		FUNCTOR2D(FrictMat,FrictViscoMat);
+		
+		YADE_CLASS_BASE_DOC_ATTRS(Ip2_FrictMat_FrictViscoMat_FrictViscoPhys,IPhysFunctor,"Converts a :yref:`FrictMat` and :yref:`FrictViscoMat` instance to :yref:`FrictViscoPhys` with corresponding parameters. Basically this functor corresponds to :yref:`Ip2_FrictMat_FrictMat_FrictPhys` with the only difference that damping in normal direction can be considered.",
+		((shared_ptr<MatchMaker>,kn,,,"Instance of :yref:`MatchMaker` determining how to compute interaction's normal contact stiffnesses. If this value is not given the elastic properties (i.e. young) of the two colliding materials are used to calculate the stiffness."))
+		((shared_ptr<MatchMaker>,kRatio,,,"Instance of :yref:`MatchMaker` determining how to compute interaction's shear contact stiffnesses. If this value is not given the elastic properties (i.e. poisson) of the two colliding materials are used to calculate the stiffness."))
+		((shared_ptr<MatchMaker>,frictAngle,,,"Instance of :yref:`MatchMaker` determining how to compute interaction's friction angle. If ``None``, minimum value is used."))
+		);
+		DECLARE_LOGGER;
+};
+REGISTER_SERIALIZABLE(Ip2_FrictMat_FrictViscoMat_FrictViscoPhys);
+
+/** 2d functor creating the interaction law (Law2) based on SphereContactGeometry (ScGeom) and FrictViscoPhys of 2 bodies, returning type FrictViscoPM */
+class Law2_ScGeom_FrictViscoPhys_CundallStrackVisco: public LawFunctor{
+	public:
+		OpenMPAccumulator<Real> plasticDissipation;
+		virtual void go(shared_ptr<IGeom>& _geom, shared_ptr<IPhys>& _phys, Interaction* I);
+		Real elasticEnergy ();
+		Real getPlasticDissipation();
+		void initPlasticDissipation(Real initVal=0);
+		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Law2_ScGeom_FrictViscoPhys_CundallStrackVisco,LawFunctor,"Constitutive law for the FrictViscoPM. Corresponds to :yref:`Law2_ScGeom_FrictPhys_CundallStrack` with the only difference that viscous damping in normal direction can be considered.",
+		((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,sphericalBodies,true,,"If true, compute branch vectors from radii (faster), else use contactPoint-position. Turning this flag true is safe for sphere-sphere contacts and a few other specific cases. It will give wrong values of torques on facets or boxes."))
+		((bool,traceEnergy,false,,"Define the total energy dissipated in plastic slips at all contacts. This will trace only plastic energy in this law, see O.trackEnergy for a more complete energies tracing"))
+		((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)"))
+		,,
+		.def("elasticEnergy",&Law2_ScGeom_FrictViscoPhys_CundallStrackVisco::elasticEnergy,"Compute and return the total elastic energy in all \"FrictViscoPhys\" contacts")
+		.def("plasticDissipation",&Law2_ScGeom_FrictViscoPhys_CundallStrackVisco::getPlasticDissipation,"Total energy dissipated in plastic slips at all FrictPhys contacts. Computed only if :yref:Law2_ScGeom_FrictViscoPhys_CundallStrackVisco::traceEnergy` is true.")
+		.def("initPlasticDissipation",&Law2_ScGeom_FrictViscoPhys_CundallStrackVisco::initPlasticDissipation,"Initialize cummulated plastic dissipation to a value (0 by default).")
+		);
+		FUNCTOR2D(ScGeom,FrictViscoPhys);
+		DECLARE_LOGGER;
+};
+REGISTER_SERIALIZABLE(Law2_ScGeom_FrictViscoPhys_CundallStrackVisco);
+
+

=== added file 'pkg/dem/GeneralIntegratorInsertionSortCollider.cpp'
--- pkg/dem/GeneralIntegratorInsertionSortCollider.cpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/GeneralIntegratorInsertionSortCollider.cpp	2014-02-17 14:31:35 +0000
@@ -0,0 +1,228 @@
+// 2009 © Václav Šmilauer <eudoxos@xxxxxxxx> 
+
+#include"GeneralIntegratorInsertionSortCollider.hpp"
+#include<yade/core/Scene.hpp>
+#include<yade/core/Interaction.hpp>
+#include<yade/core/InteractionContainer.hpp>
+#include<yade/pkg/common/Dispatching.hpp>
+#include<yade/pkg/dem/Integrator.hpp>
+#include<yade/pkg/common/Sphere.hpp>
+
+#include<algorithm>
+#include<vector>
+#include<boost/static_assert.hpp>
+
+using namespace std;
+
+YADE_PLUGIN((GeneralIntegratorInsertionSortCollider))
+CREATE_LOGGER(GeneralIntegratorInsertionSortCollider);
+
+// STRIDE
+bool GeneralIntegratorInsertionSortCollider::isActivated(){
+		// activated if number of bodies changes (hence need to refresh collision information)
+		// or the time of scheduled run already came, or we were never scheduled yet
+		if(!strideActive) return true;
+		if(!integrator) return true;
+		if(fastestBodyMaxDist<0){fastestBodyMaxDist=0; return true;}
+		fastestBodyMaxDist=integrator->maxVelocitySq;
+		if(fastestBodyMaxDist>=1 || fastestBodyMaxDist==0) return true;
+		if((size_t)BB[0].size!=2*scene->bodies->size()) return true;
+		if(scene->interactions->dirty) return true;
+		if(scene->doSort) { scene->doSort=false; return true; }
+		return false;
+	}
+
+void GeneralIntegratorInsertionSortCollider::action(){
+	#ifdef ISC_TIMING
+		timingDeltas->start();
+	#endif
+
+	long nBodies=(long)scene->bodies->size();
+	InteractionContainer* interactions=scene->interactions.get();
+	scene->interactions->iterColliderLastRun=-1;
+
+	// periodicity changed, force reinit
+	if(scene->isPeriodic != periodic){
+		for(int i=0; i<3; i++) BB[i].vec.clear();
+		periodic=scene->isPeriodic;
+	}
+	// pre-conditions
+		// adjust storage size
+		bool doInitSort=false;
+		if (doSort) {
+			doInitSort=true;
+			doSort=false;
+		}
+		if(BB[0].size!=2*nBodies){
+			long BBsize=BB[0].size;
+			LOG_DEBUG("Resize bounds containers from "<<BBsize<<" to "<<nBodies*2<<", will std::sort.");
+			// bodies deleted; clear the container completely, and do as if all bodies were added (rather slow…)
+			// future possibility: insertion sort with such operator that deleted bodies would all go to the end, then just trim bounds
+			if(2*nBodies<BBsize){ for(int i=0; i<3; i++) BB[i].vec.clear(); }
+			// more than 100 bodies was added, do initial sort again
+			// maybe: should rather depend on ratio of added bodies to those already present...?
+			if(2*nBodies-BBsize>200 || BBsize==0) doInitSort=true;
+			assert((BBsize%2)==0);
+			for(int i=0; i<3; i++){
+				BB[i].vec.reserve(2*nBodies);
+				// add lower and upper bounds; coord is not important, will be updated from bb shortly
+				for(long id=BBsize/2; id<nBodies; id++){ BB[i].vec.push_back(Bounds(0,id,/*isMin=*/true)); BB[i].vec.push_back(Bounds(0,id,/*isMin=*/false)); }
+				BB[i].size=BB[i].vec.size();
+			}
+		}
+		if(minima.size()!=(size_t)3*nBodies){ minima.resize(3*nBodies); maxima.resize(3*nBodies); }
+		assert((size_t)BB[0].size==2*scene->bodies->size());
+
+		// update periodicity
+		assert(BB[0].axis==0); assert(BB[1].axis==1); assert(BB[2].axis==2);
+		if(periodic) for(int i=0; i<3; i++) BB[i].updatePeriodicity(scene);
+
+		// compatibility block, can be removed later
+		findBoundDispatcherInEnginesIfNoFunctorsAndWarn();
+
+		if(verletDist<0){
+			Real minR=std::numeric_limits<Real>::infinity();
+			FOREACH(const shared_ptr<Body>& b, *scene->bodies){
+				if(!b || !b->shape) continue;
+				Sphere* s=dynamic_cast<Sphere*>(b->shape.get());
+				if(!s) continue;
+				minR=min(s->radius,minR);
+			}
+			if (isinf(minR)) LOG_ERROR("verletDist is set to 0 because no spheres were found. It will result in suboptimal performances, consider setting a positive verletDist in your script.");
+			// if no spheres, disable stride
+			verletDist=isinf(minR) ? 0 : abs(verletDist)*minR;
+		}
+		
+		// update bounds via boundDispatcher
+		boundDispatcher->scene=scene;
+		boundDispatcher->sweepDist=verletDist;
+		boundDispatcher->minSweepDistFactor=minSweepDistFactor;
+		boundDispatcher->targetInterv=targetInterv;
+		boundDispatcher->updatingDispFactor=updatingDispFactor;
+		boundDispatcher->action();
+
+		// if interactions are dirty, force reinitialization
+		if(scene->interactions->dirty){
+			doInitSort=true;
+			scene->interactions->dirty=false;
+		}
+		
+		// STRIDE
+		if(verletDist>0){
+			// get the Integrator, to ask for the maximum velocity value
+			if(!integrator){
+ 				FOREACH(shared_ptr<Engine>& e, scene->engines){ integrator=dynamic_pointer_cast<Integrator>(e); if(integrator) break; }
+				if(!integrator){ throw runtime_error("InsertionSortCollider.verletDist>0, but unable to locate any Integrator within O.engines."); }
+			}
+		}
+	ISC_CHECKPOINT("init");
+
+		// STRIDE
+			// get us ready for strides, if they were deactivated
+			if(!strideActive && verletDist>0 && integrator->maxVelocitySq>=0){ // maxVelocitySq is a really computed value
+				strideActive=true;
+			}
+			if(strideActive){
+				assert(verletDist>0);
+				assert(strideActive); assert(integrator->maxVelocitySq>=0);
+					integrator->updatingDispFactor=updatingDispFactor;
+			} else { /* !strideActive */
+				boundDispatcher->sweepDist=0;
+			}
+
+	ISC_CHECKPOINT("bound");
+
+	// copy bounds along given axis into our arrays
+		for(long i=0; i<2*nBodies; i++){
+			for(int j=0; j<3; j++){
+				VecBounds& BBj=BB[j];
+				const Body::id_t id=BBj[i].id;
+				const shared_ptr<Body>& b=Body::byId(id,scene);
+				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!)
+					
+					BBj[i].coord=((BBj[i].flags.hasBB=((bool)bv)) ? (BBj[i].flags.isMin ? bv->min[j] : bv->max[j]) : (b->state->pos[j])) - (periodic ? BBj.cellDim*BBj[i].period : 0.);
+					
+				} else { BBj[i].flags.hasBB=false; /* for vanished body, keep the coordinate as-is, to minimize inversions. */ }
+				// if initializing periodic, shift coords & record the period into BBj[i].period
+				if(doInitSort && periodic) {
+					BBj[i].coord=cellWrap(BBj[i].coord,0,BBj.cellDim,BBj[i].period);
+				}
+			}	
+		}
+	// for each body, copy its minima and maxima, for quick checks of overlaps later
+	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(b){
+			const shared_ptr<Bound>& bv=b->bound;
+			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)); }
+	}
+
+	ISC_CHECKPOINT("copy");
+
+	// process interactions that the constitutive law asked to be erased
+// 	interactions->erasePending(*this,scene);
+	interactions->conditionalyEraseNonReal(*this,scene);
+	
+	ISC_CHECKPOINT("erase");
+
+	// sort
+		// the regular case
+		if(!doInitSort && !sortThenCollide){
+			/* each inversion in insertionSort calls handleBoundInversion, which in turns may add/remove interaction */
+			if(!periodic) for(int i=0; i<3; i++) insertionSort(BB[i],interactions,scene); 
+			else for(int i=0; i<3; i++) insertionSortPeri(BB[i],interactions,scene);
+		}
+		// create initial interactions (much slower)
+		else {
+			if(doInitSort){
+				// the initial sort is in independent in 3 dimensions, may be run in parallel; it seems that there is no time gain running in parallel, though
+				// important to reset loInx for periodic simulation (!!)
+				for(int i=0; i<3; i++) { BB[i].loIdx=0; std::sort(BB[i].vec.begin(),BB[i].vec.end()); }
+				numReinit++;
+			} else { // sortThenCollide
+				if(!periodic) for(int i=0; i<3; i++) insertionSort(BB[i],interactions,scene,false);
+				else for(int i=0; i<3; i++) insertionSortPeri(BB[i],interactions,scene,false);
+			}
+			// traverse the container along requested axis
+			assert(sortAxis==0 || sortAxis==1 || sortAxis==2);
+			VecBounds& V=BB[sortAxis];
+			// go through potential aabb collisions, create interactions as necessary
+			if(!periodic){
+				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(!(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++){
+						const Body::id_t& jid=V[j].id;
+						// take 2 of the same condition (only handle collision [min_i..max_i]+min_j, not [min_i..max_i]+min_i (symmetric)
+						if(!V[j].flags.isMin) continue;
+						/* abuse the same function here; since it does spatial overlap check first, it is OK to use it */
+						handleBoundInversion(iid,jid,interactions,scene);
+						assert(j<2*nBodies-1);
+					}
+				}
+			} else { // periodic case: see comments above
+				for(long i=0; i<2*nBodies; i++){
+					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
+					for(long j=V.norm(i+1); V[j].id!=iid; j=V.norm(j+1)){
+						const Body::id_t& jid=V[j].id;
+						if(!V[j].flags.isMin) continue;
+						handleBoundInversionPeri(iid,jid,interactions,scene);
+						if(cnt++>2*(long)nBodies){ LOG_FATAL("Uninterrupted loop in the initial sort?"); throw std::logic_error("loop??"); }
+					}
+				}
+			}
+		}
+	ISC_CHECKPOINT("sort&collide");
+}

=== added file 'pkg/dem/GeneralIntegratorInsertionSortCollider.hpp'
--- pkg/dem/GeneralIntegratorInsertionSortCollider.hpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/GeneralIntegratorInsertionSortCollider.hpp	2014-02-17 14:31:35 +0000
@@ -0,0 +1,39 @@
+// 2014 Burak ER <burak.er@xxxxxxxxxx> 
+
+#pragma once
+#include<yade/pkg/common/InsertionSortCollider.hpp>
+
+
+/*!
+	Adaptive Integration Sort Collider:
+
+	Changing the Integrator dependence from Newton Integrator to Arbitrary Integrators. Arbitrary integrators should use the Integrator interface. 
+
+*/
+
+
+
+#ifdef ISC_TIMING
+	#define ISC_CHECKPOINT(cpt) timingDeltas->checkpoint(cpt)
+#else
+	#define ISC_CHECKPOINT(cpt)
+#endif
+
+class Integrator;
+
+class GeneralIntegratorInsertionSortCollider: public InsertionSortCollider{
+
+	// we need this to find out about current maxVelocitySq
+	shared_ptr<Integrator> integrator;
+	// if False, no type of striding is used
+
+	public:
+
+	virtual bool isActivated(); //override this function to change NewtonIntegrator dependency.
+
+	virtual void action(); //override this function to change behaviour with the NewtonIntegrator dependency.
+
+	YADE_CLASS_BASE_DOC(GeneralIntegratorInsertionSortCollider,InsertionSortCollider," This class is the adaptive version of the InsertionSortCollider and changes the NewtonIntegrator dependency of the collider algorithms to the Integrator interface which is more general.");
+	DECLARE_LOGGER;
+};
+REGISTER_SERIALIZABLE(GeneralIntegratorInsertionSortCollider);

=== added file 'pkg/dem/Integrator.cpp'
--- pkg/dem/Integrator.cpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/Integrator.cpp	2014-02-17 14:31:35 +0000
@@ -0,0 +1,351 @@
+#include<yade/core/Clump.hpp>
+#include<yade/core/Scene.hpp>
+#include<yade/pkg/dem/Integrator.hpp>
+#include<boost/python.hpp>
+using namespace boost;
+#ifdef YADE_OPENMP
+  #include<omp.h>
+#endif
+
+YADE_PLUGIN((Integrator));
+
+
+
+void observer::operator()( const stateVector&  x , Real  t ) const
+{
+	this->integrator->scene->time=t;
+
+	this->integrator->setCurrentStates(x);
+	
+}
+
+
+//! Integrator's pseudo-ctor (factory), taking nested lists of slave engines (might be moved to real ctor perhaps)
+
+
+void Integrator::action(){
+
+
+}
+
+void Integrator::system(const stateVector& currentstates, stateVector& derivatives, Real time)
+{
+
+	#ifdef YADE_OPENMP
+	//prevent https://bugs.launchpad.net/yade/+bug/923929
+		ensureSync();
+	#endif
+
+	//Calculate orientation
+
+	maxVelocitySq=-1;
+
+	setCurrentStates(currentstates);
+	
+	scene->time=time;
+	
+	const int size=(int)slaves.size();
+
+	for(int i=0; i<size; i++){
+		// run every slave group sequentially
+		FOREACH(const shared_ptr<Engine>& e, slaves[i]) {
+			e->scene=scene;
+			if(!e->dead && e->isActivated()) e->action();
+		}
+	}
+	derivatives=getSceneStateDot();
+	
+/*
+	std::cout<<std::endl<<"Derivatives are"<<std::endl;
+	for(long int k=0;k<derivatives.size();k++)
+	std::cout<<std::endl<<derivatives[k]<<std::endl;*/
+}
+
+stateVector& Integrator::getSceneStateDot(void){
+	
+	try{
+
+		long int numberofscenebodies=scene->bodies->size();
+	
+		scene->forces.sync();
+	
+		accumstatedotofthescene.resize(2*scene->bodies->size()*7);
+
+		YADE_PARALLEL_FOREACH_BODY_BEGIN(const shared_ptr<Body>& b, scene->bodies){
+		
+		const Body::id_t& id=b->getId();	
+
+	 	Vector3r force=Vector3r::Zero();	
+
+		Vector3r vel_current;
+
+		Vector3r moment=Vector3r::Zero();
+		
+		Vector3r angvel_current;
+		
+		Quaternionr ori_current;
+
+		Quaternionr angvelquat;
+
+		Quaternionr oridot_current;
+
+		if(!b->isClumpMember()) {
+	
+			Real mass=b->state->mass;
+		
+			Vector3r inertia=b->state->inertia;	
+
+			vel_current=b->state->vel;
+	
+			angvel_current=b->state->angVel;
+
+			ori_current=b->state->ori;
+
+			// clumps forces
+			if(b->isClump()) {
+				b->shape->cast<Clump>().addForceTorqueFromMembers(b->state.get(),scene,force,moment);
+				#ifdef YADE_OPENMP
+				//it is safe here, since only one thread will read/write
+				scene->forces.getTorqueUnsynced(id)+=moment;
+				scene->forces.getForceUnsynced(id)+=force;
+				#else
+				scene->forces.addTorque(id,moment);
+				scene->forces.addForce(id,force);
+				#endif
+			}
+
+                
+			force=scene->forces.getForce(id); moment=scene->forces.getTorque(id);
+		
+			/*
+			 *	Calculation of accelerations
+			 *
+			*/
+	
+		
+			force[0]=force[0]/mass;	force[1]= force[1]/mass;	force[2]= force[2]/mass; //Calculate linear acceleration
+	
+			moment[0]=moment[0]/inertia[0];	moment[1]= moment[1]/inertia[1];	moment[2]= moment[2]/inertia[2]; //Calculate angular acceleration
+
+			//Check for fixation 
+			/*
+				This code block needs optimization
+			*/
+			string str="xyzXYZ"; // Very very very hard coding!!!!! Fixation seems not handled fine by state structure, should be improved.
+			
+			for(int i=0; i<3; i++) if(b->state->blockedDOFs_vec_get().find(str[i]) != std::string::npos){ force[i]=0;vel_current[i]=0;}
+			for(int i=3; i<6; i++) if(b->state->blockedDOFs_vec_get().find(str[i]) != std::string::npos){ moment[i-3]=0;angvel_current[i-3]=0;}
+
+			angvelquat = Quaternionr(0.0,angvel_current[0],angvel_current[1],angvel_current[2]);	
+					
+			oridot_current=0.5*angvelquat*ori_current;
+
+		
+			//	if (densityScaling) accel*=state->densityScaling;
+
+		}
+		else
+		{
+
+			//is clump member
+			force=Vector3r::Zero();
+			moment=Vector3r::Zero();
+			vel_current=Vector3r::Zero();	
+		        angvel_current=Vector3r::Zero();
+			oridot_current=Quaternionr(0,0,0,0);// zero change in quaternion with respect to time
+		}
+
+
+		/*Orientation differantion is straight forward.*/
+		accumstatedotofthescene[id*7+0]=vel_current[0]; 	accumstatedotofthescene[(id+numberofscenebodies)*7+0]=force[0];
+		accumstatedotofthescene[id*7+1]=vel_current[1];		accumstatedotofthescene[(id+numberofscenebodies)*7+1]=force[1];
+		accumstatedotofthescene[id*7+2]=vel_current[2];		accumstatedotofthescene[(id+numberofscenebodies)*7+2]=force[2];
+		accumstatedotofthescene[id*7+3]=oridot_current.w();	accumstatedotofthescene[(id+numberofscenebodies)*7+3]=moment[0];
+		accumstatedotofthescene[id*7+4]=oridot_current.x();	accumstatedotofthescene[(id+numberofscenebodies)*7+4]=moment[1];
+		accumstatedotofthescene[id*7+5]=oridot_current.y();	accumstatedotofthescene[(id+numberofscenebodies)*7+5]=moment[2];
+		accumstatedotofthescene[id*7+6]=oridot_current.z();	accumstatedotofthescene[(id+numberofscenebodies)*7+6]=0;
+
+
+		} YADE_PARALLEL_FOREACH_BODY_END();
+	
+	
+	}
+	catch(std::exception& e){
+
+		LOG_FATAL("Unhandled exception at Integrator::getSceneStateDot the exception information : "<<typeid(e).name()<<" : "<<e.what());
+	}
+
+	return accumstatedotofthescene;
+
+
+
+}
+
+
+
+stateVector& Integrator::getCurrentStates(void)
+{
+
+
+	try{
+
+		long int numberofscenebodies=scene->bodies->size();
+
+		accumstateofthescene.resize(2*scene->bodies->size()*7);
+	
+		YADE_PARALLEL_FOREACH_BODY_BEGIN(const shared_ptr<Body>& b, scene->bodies){
+		
+		const Body::id_t& id=b->getId();	
+				
+         	Vector3r pos_current=b->state->pos;		
+
+		Vector3r vel_current=b->state->vel;
+
+		Quaternionr ori=b->state->ori;
+		
+		Vector3r angvel=b->state->angVel;
+
+		accumstateofthescene[id*7+0]=pos_current[0]; 	accumstateofthescene[(id+numberofscenebodies)*7+0]=vel_current[0];
+		accumstateofthescene[id*7+1]=pos_current[1];	accumstateofthescene[(id+numberofscenebodies)*7+1]=vel_current[1];
+		accumstateofthescene[id*7+2]=pos_current[2];	accumstateofthescene[(id+numberofscenebodies)*7+2]=vel_current[2];
+		accumstateofthescene[id*7+3]=ori.w();		accumstateofthescene[(id+numberofscenebodies)*7+3]=angvel[0];
+		accumstateofthescene[id*7+4]=ori.x();		accumstateofthescene[(id+numberofscenebodies)*7+4]=angvel[1];
+		accumstateofthescene[id*7+5]=ori.y();		accumstateofthescene[(id+numberofscenebodies)*7+5]=angvel[2];
+		accumstateofthescene[id*7+6]=ori.z();		accumstateofthescene[(id+numberofscenebodies)*7+6]=0;
+
+
+		} YADE_PARALLEL_FOREACH_BODY_END();
+	
+	
+	}
+	catch(std::exception& e){
+
+		LOG_FATAL("Unhandled exception at Integrator::getCurrentStates the exception information : "<<typeid(e).name()<<" : "<<e.what());
+	}
+
+	return accumstateofthescene;
+
+}
+
+bool Integrator::setCurrentStates(stateVector yscene)
+{
+		
+	try{
+
+		long int numberofscenebodies=scene->bodies->size();
+
+		//Zero max velocity for each thread	
+		#ifdef YADE_OPENMP
+			FOREACH(Real& thrMaxVSq, threadMaxVelocitySq) { thrMaxVSq=0; }
+		#endif
+
+		YADE_PARALLEL_FOREACH_BODY_BEGIN(const shared_ptr<Body>& b, scene->bodies){
+
+		if(b->isClumpMember()) continue;
+		
+		const Body::id_t& id=b->getId();
+		
+         	Vector3r pos_current;		
+
+		pos_current<<yscene[id*7+0],yscene[id*7+1],yscene[id*7+2];
+
+		Vector3r vel_current;
+	
+		vel_current<<yscene[(id+numberofscenebodies)*7+0],yscene[(id+numberofscenebodies)*7+1],yscene[(id+numberofscenebodies)*7+2];
+		
+		Quaternionr ori=Quaternionr(yscene[id*7+3],yscene[id*7+4],yscene[id*7+5],yscene[id*7+6]);
+
+		Vector3r angvel;
+
+		angvel<<yscene[(id+numberofscenebodies)*7+3],yscene[(id+numberofscenebodies)*7+4],yscene[(id+numberofscenebodies)*7+5];
+                
+                b->state->pos=pos_current;
+                
+                b->state->vel=vel_current;
+	
+		b->state->ori=ori;
+		
+		//std::cout<<"Setting orientation to "<<ori<<std::endl;
+
+		b->state->ori.normalize(); //Normalize orientation
+
+		//std::cout<<"Setting angvel to "<<angvel<<std::endl;
+
+                b->state->angVel=angvel;
+
+		#ifdef YADE_OPENMP
+			Real& thrMaxVSq=threadMaxVelocitySq[omp_get_thread_num()]; thrMaxVSq=max(thrMaxVSq,b->state->vel.squaredNorm());
+		#else
+			maxVelocitySq=max(maxVelocitySq,b->state->vel.squaredNorm());// Set maximum velocity of the scene
+		#endif
+
+		if(b->isClump()) Clump::moveMembers(b,scene,this);
+
+		} YADE_PARALLEL_FOREACH_BODY_END();
+	
+		#ifdef YADE_OPENMP
+			FOREACH(const Real& thrMaxVSq, threadMaxVelocitySq) { maxVelocitySq=max(maxVelocitySq,thrMaxVSq); }
+		#endif
+
+	
+	}
+	catch(std::exception& e){
+
+		LOG_FATAL("Unhandled exception at Integrator::setCurrentStates the exception information : "<<typeid(e).name()<<" : "<<e.what());
+
+		return false;
+	}
+
+	return true;
+}
+
+
+#ifdef YADE_OPENMP
+void Integrator::ensureSync()
+{
+	if (syncEnsured) return;	
+	YADE_PARALLEL_FOREACH_BODY_BEGIN(const shared_ptr<Body>& b, scene->bodies){
+// 		if(b->isClump()) continue;
+		scene->forces.addForce(b->getId(),Vector3r(0,0,0));
+	} YADE_PARALLEL_FOREACH_BODY_END();
+	syncEnsured=true;
+}
+#endif
+
+
+void Integrator::saveMaximaDisplacement(const shared_ptr<Body>& b){
+	if (!b->bound) return;//clumps for instance, have no bounds, hence not saved
+	Vector3r disp=b->state->pos-b->bound->refPos;
+	Real maxDisp=max(abs(disp[0]),max(abs(disp[1]),abs(disp[2])));
+	if (!maxDisp || maxDisp<b->bound->sweepLength) {/*b->bound->isBounding = (updatingDispFactor>0 && (updatingDispFactor*maxDisp)<b->bound->sweepLength);*/
+	maxDisp=0.5;//not 0, else it will be seen as "not updated" by the collider, but less than 1 means no colliding
+	}
+	else {/*b->bound->isBounding = false;*/ maxDisp=2;/*2 is more than 1, enough to trigger collider*/}
+	
+	maxVelocitySq=max(maxVelocitySq,maxDisp);
+}
+
+void Integrator::slaves_set(const python::list& slaves2){
+std::cout<<"Adding slaves";
+	int len=python::len(slaves2);
+	slaves.clear();
+	for(int i=0; i<len; i++){
+		python::extract<std::vector<shared_ptr<Engine> > > serialGroup(slaves2[i]);
+		if (serialGroup.check()){ slaves.push_back(serialGroup()); continue; }
+		python::extract<shared_ptr<Engine> > serialAlone(slaves2[i]);
+		if (serialAlone.check()){ vector<shared_ptr<Engine> > aloneWrap; aloneWrap.push_back(serialAlone()); slaves.push_back(aloneWrap); continue; }
+		PyErr_SetString(PyExc_TypeError,"Engines that are given to Integrator should be in two cases (a) in an ordered group, (b) alone engines");
+		python::throw_error_already_set();
+	}
+}
+
+python::list Integrator::slaves_get(){
+	python::list ret;
+	FOREACH(vector<shared_ptr<Engine > >& grp, slaves){
+		if(grp.size()==1) ret.append(python::object(grp[0]));
+		else ret.append(python::object(grp));
+	}
+	return ret;
+}
+
+

=== added file 'pkg/dem/Integrator.hpp'
--- pkg/dem/Integrator.hpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/Integrator.hpp	2014-02-17 14:31:35 +0000
@@ -0,0 +1,113 @@
+#pragma once
+
+#include<yade/core/TimeStepper.hpp>
+#include<boost/python.hpp>
+
+class Integrator;
+
+
+typedef std::vector<Real> stateVector;// Currently, we are unable to use Eigen library within odeint
+
+/*Observer used to update the state of the scene*/
+class observer
+{
+	Integrator* integrator;
+public:
+	observer(Integrator* _in):integrator(_in){}
+        void operator()( const stateVector& /* x */ , Real /* t */ ) const;
+};
+
+//[ ode_wrapper
+template< class Obj , class Mem >
+class ode_wrapper
+{
+    Obj m_obj;
+    Mem m_mem;
+
+public:
+
+    ode_wrapper( Obj obj , Mem mem ) : m_obj( obj ) , m_mem( mem ) { }
+
+    template< class State , class Deriv , class Time >
+    void operator()( const State &x , Deriv &dxdt , Time t )
+    {
+        (m_obj.*m_mem)( x , dxdt , t );
+    }
+};
+
+template< class Obj , class Mem >
+ode_wrapper< Obj , Mem > make_ode_wrapper( Obj obj , Mem mem )
+{
+    return ode_wrapper< Obj , Mem >( obj , mem );
+}
+//]
+
+
+
+class Integrator: public TimeStepper {
+
+		public:
+
+		stateVector accumstateofthescene;//pos+vel
+		
+		stateVector accumstatedotofthescene;//only the accelerations
+
+		stateVector resetstate;//last state before integration attempt
+	
+		Real timeresetvalue;
+
+		inline void evaluateQuaternions(const stateVector &); //evaluate quaternions after integration
+
+		typedef vector<vector<shared_ptr<Engine> > > slaveContainer;
+
+		#ifdef YADE_OPENMP
+			vector<Real> threadMaxVelocitySq;
+		#endif
+	
+		virtual void action();
+
+		virtual void system(const stateVector&, stateVector&, Real); //System function to calculate the derivatives of states
+
+		virtual bool isActivated(){return true;}
+		// py access
+		boost::python::list slaves_get();
+
+		stateVector& getSceneStateDot();
+
+		bool saveCurrentState(Scene const* ourscene);//Before any integration attempt state of the scene should be saved. 
+
+		bool resetLastState(void);//Before any integration attempt state of the scene should be saved. 
+
+		void slaves_set(const boost::python::list& slaves);
+	
+		stateVector& getCurrentStates(void);
+
+		bool setCurrentStates(stateVector);	
+
+		Real updatingDispFactor;//(experimental) Displacement factor used to trigger bound update: the bound is updated only if updatingDispFactor*disp>sweepDist when >0, else all bounds are updated.	
+
+		void saveMaximaDisplacement(const shared_ptr<Body>& b);
+
+		#ifdef YADE_OPENMP
+			void ensureSync(); bool syncEnsured;
+		#endif
+
+
+		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(Integrator,TimeStepper,"Integration Engine Interface.",
+		((slaveContainer,slaves,,,"[will be overridden]"))
+		((Real,integrationsteps,,,"all integrationsteps count as all succesfull substeps"))
+		((Real,maxVelocitySq,NaN,,"store square of max. velocity, for informative purposes; computed again at every step. |yupdate|"))
+		,
+		/*ctor*/
+		#ifdef YADE_OPENMP
+			threadMaxVelocitySq.resize(omp_get_max_threads()); syncEnsured=false;
+		#endif
+		,
+		/*py*/
+
+		.add_property("slaves",&Integrator::slaves_get,&Integrator::slaves_set,"List of lists of Engines to calculate the force acting on the particles;  to obtain the derivatives of the states, engines inside will be run sequentially.");
+	);
+};
+REGISTER_SERIALIZABLE(Integrator);
+
+

=== modified file 'pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.cpp'
--- pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.cpp	2013-03-06 20:47:43 +0000
+++ pkg/dem/Ip2_CohFrictMat_CohFrictMat_CohFrictPhys.cpp	2014-01-24 17:15:20 +0000
@@ -43,7 +43,9 @@
 
 			// harmonic average of alphas parameters
 			Real AlphaKr = 2.0*sdec1->alphaKr*sdec2->alphaKr/(sdec1->alphaKr+sdec2->alphaKr);
-			Real AlphaKtw = 2.0*sdec1->alphaKtw*sdec2->alphaKtw/(sdec1->alphaKtw+sdec2->alphaKtw);
+			Real AlphaKtw;
+			if (sdec1->alphaKtw && sdec2->alphaKtw) AlphaKtw = 2.0*sdec1->alphaKtw*sdec2->alphaKtw/(sdec1->alphaKtw+sdec2->alphaKtw);
+			else AlphaKtw=0;
 
 			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

=== modified file 'pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.cpp'
--- pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.cpp	2012-06-04 21:03:29 +0000
+++ pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.cpp	2014-01-23 10:25:43 +0000
@@ -13,6 +13,7 @@
 #include<yade/core/Omega.hpp>
 #include<yade/core/Scene.hpp>
 #include<yade/pkg/common/ElastMat.hpp>
+#include<yade/pkg/dem/ViscoelasticPM.hpp>
 #include <cassert>
 
 
@@ -22,8 +23,16 @@
 					, const shared_ptr<Interaction>& interaction)
 {
 	if(interaction->phys) return;
+	
 	const shared_ptr<FrictMat>& mat1 = YADE_PTR_CAST<FrictMat>(b1);
 	const shared_ptr<FrictMat>& mat2 = YADE_PTR_CAST<FrictMat>(b2);
+	
+	Real Ra,Rb;//Vector3r normal;
+	assert(dynamic_cast<GenericSpheresContact*>(interaction->geom.get()));//only in debug mode
+	GenericSpheresContact* sphCont=YADE_CAST<GenericSpheresContact*>(interaction->geom.get());
+	Ra=sphCont->refR1>0?sphCont->refR1:sphCont->refR2;
+	Rb=sphCont->refR2>0?sphCont->refR2:sphCont->refR1;
+	
 	interaction->phys = shared_ptr<FrictPhys>(new FrictPhys());
 	const shared_ptr<FrictPhys>& contactPhysics = YADE_PTR_CAST<FrictPhys>(interaction->phys);
 	Real Ea 	= mat1->young;
@@ -31,13 +40,7 @@
 	Real Va 	= mat1->poisson;
 	Real Vb 	= mat2->poisson;
 
-	Real Ra,Rb;//Vector3r normal;
-	assert(dynamic_cast<GenericSpheresContact*>(interaction->geom.get()));//only in debug mode
-	GenericSpheresContact* sphCont=YADE_CAST<GenericSpheresContact*>(interaction->geom.get());
-	Ra=sphCont->refR1>0?sphCont->refR1:sphCont->refR2;
-	Rb=sphCont->refR2>0?sphCont->refR2:sphCont->refR1;
-
-	//harmonic average of the two stiffnesses when (Ri.Ei/2) is the stiffness of a contact point on sphere "i"
+	//harmonic average of the two stiffnesses when (2*Ri*Ei) is the stiffness of a contact point on sphere "i"
 	Real Kn = 2*Ea*Ra*Eb*Rb/(Ea*Ra+Eb*Rb);
 	//same for shear stiffness
 	Real Ks = 2*Ea*Ra*Va*Eb*Rb*Vb/(Ea*Ra*Va+Eb*Rb*Vb);
@@ -72,7 +75,7 @@
 	//harmonic average of the two stiffnesses when (Ri.Ei/2) is the stiffness of a contact point on sphere "i"
 	Real Kn = 2*Ea*Ra*Eb*Rb/(Ea*Ra+Eb*Rb);
 	//same for shear stiffness
-	Real Ks = 2*Ea*Ra*Va*Eb*Rb*Vb/(Ea*Ra*Va+Eb*Rb*Va);
+	Real Ks = 2*Ea*Ra*Va*Eb*Rb*Vb/(Ea*Ra*Va+Eb*Rb*Vb);
 
 	Real frictionAngle = (!frictAngle) ? std::min(mat1->frictionAngle,mat2->frictionAngle) : (*frictAngle)(mat1->id,mat2->id,mat1->frictionAngle,mat2->frictionAngle);
 	contactPhysics->tangensOfFrictionAngle = std::tan(frictionAngle);

=== modified file 'pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.hpp'
--- pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.hpp	2013-02-26 19:38:41 +0000
+++ pkg/dem/Ip2_FrictMat_FrictMat_FrictPhys.hpp	2014-01-23 10:25:43 +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 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.",
+	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. In the case of a contact between a :yref:`ViscElMat` and a :yref:`FrictMat`, be sure to set :yref:`FrictMat::young` and :yref:`FrictMat::poisson`, otherwise the default value will be used.",
 		((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/JointedCohesiveFrictionalPM.cpp'
--- pkg/dem/JointedCohesiveFrictionalPM.cpp	2013-11-05 10:52:25 +0000
+++ pkg/dem/JointedCohesiveFrictionalPM.cpp	2014-01-29 11:27:31 +0000
@@ -42,7 +42,7 @@
 	
 	if ( smoothJoint && phys->isOnJoint ) {
 	  if ( phys->more || ( phys->jointCumulativeSliding > (2*min(geom->radius1,geom->radius2)) ) ) { 
-	    scene->interactions->requestErase(contact->getId1(),contact->getId2()); return; 
+	    scene->interactions->requestErase(contact); return; 
 	    } else { 
 	    D = phys->initD - abs((b1->state->pos - b2->state->pos).dot(phys->jointNormal)); 
 	    }
@@ -52,7 +52,7 @@
 
 	/* Determination of interaction */
 	if (D < 0) { //spheres do not touch 
-	  if ( !phys->isCohesive ) { scene->interactions->requestErase(contact->getId1(),contact->getId2()); return; }
+	  if ( !phys->isCohesive ) { scene->interactions->requestErase(contact); return; }
 	  
 	  if ( phys->isCohesive && (phys->FnMax>0) && (abs(D)>Dtensile) ) {
 	    
@@ -75,7 +75,7 @@
 	    cracksFileExist=true;
 
 	    // delete contact
-	    scene->interactions->requestErase(contact->getId1(),contact->getId2()); return;
+	    scene->interactions->requestErase(contact); return;
 	  }
 	}	  
 	
@@ -136,7 +136,7 @@
 	    
 	    // delete contact if in tension, set the contact properties to friction if in compression
 	    if ( D < 0 ) {
-	      scene->interactions->requestErase(contact->getId1(),contact->getId2()); return;
+	      scene->interactions->requestErase(contact); return;
 	    } else {
 	      phys->FnMax = 0;
 	      phys->FsMax = 0;

=== modified file 'pkg/dem/JointedCohesiveFrictionalPM.hpp'
--- pkg/dem/JointedCohesiveFrictionalPM.hpp	2013-11-05 10:52:25 +0000
+++ pkg/dem/JointedCohesiveFrictionalPM.hpp	2013-12-05 11:49:29 +0000
@@ -34,7 +34,7 @@
 		virtual bool stateTypeOk(State* s) const { return (bool)dynamic_cast<JCFpmState*>(s); }
 		
 	YADE_CLASS_BASE_DOC_ATTRS_CTOR(JCFpmMat,FrictMat,"Possibly jointed, cohesive frictional material, for use with other JCFpm classes",
-		((Real,cohesion,0.,,"Defines the maximum admissible tangential force in shear, for Fn=0, in the matrix (:yref:`FsMax<JCFpmPhys.FsMax>` = cohesion*:yref:`crossSection<JCFpmPhys.crossSection>`). [Pa]"))
+		((Real,cohesion,0.,,"Defines the maximum admissible tangential force in shear, for Fn=0, in the matrix (:yref:`FsMax<JCFpmPhys.FsMax>` = cohesion * :yref:`crossSection<JCFpmPhys.crossSection>`). [Pa]"))
 		((Real,jointCohesion,0.,,"Defines the :yref:`maximum admissible tangential force in shear<JCFpmPhys.FsMax>`, for Fn=0, on the joint surface. [Pa]"))
 		((Real,jointDilationAngle,0,,"Defines the dilatancy of the joint surface (only valid for :yref:`smooth contact logic<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM.smoothJoint>`). [rad]"))	
 		((Real,jointFrictionAngle,-1,,"Defines Coulomb friction on the joint surface. [rad]"))
@@ -42,7 +42,7 @@
 		((Real,jointShearStiffness,0.,,"Defines the shear stiffness on the joint surface. [Pa/m]"))
 		((Real,jointTensileStrength,0.,,"Defines the :yref:`maximum admissible normal force in traction<JCFpmPhys.FnMax>` on the joint surface. [Pa]"))
 		((int,type,0,,"If particles of two different types interact, it will be with friction only (no cohesion).[-]"))
-		((Real,tensileStrength,0.,,"Defines the maximum admissible normal force in traction in the matrix (:yref:`FnMax<JCFpmPhys.FnMax>` = tensileStrength*:yref:`crossSection<JCFpmPhys.crossSection>`). [Pa]"))
+		((Real,tensileStrength,0.,,"Defines the maximum admissible normal force in traction in the matrix (:yref:`FnMax<JCFpmPhys.FnMax>` = tensileStrength * :yref:`crossSection<JCFpmPhys.crossSection>`). [Pa]"))
 		,
 		createIndex();
 	);

=== modified file 'pkg/dem/L3Geom.hpp'
--- pkg/dem/L3Geom.hpp	2013-08-23 15:21:20 +0000
+++ pkg/dem/L3Geom.hpp	2014-01-20 16:14:58 +0000
@@ -33,7 +33,7 @@
 
 struct L3Geom: public GenericSpheresContact{
 	const Real& uN;
-	const Vector2r& uT; 
+	const Vector2r uT; 
 	virtual ~L3Geom();
 
 	// utility function

=== modified file 'pkg/dem/NewtonIntegrator.cpp'
--- pkg/dem/NewtonIntegrator.cpp	2013-05-14 21:24:11 +0000
+++ pkg/dem/NewtonIntegrator.cpp	2014-02-16 14:03:41 +0000
@@ -224,7 +224,7 @@
 	//NOTE : dVel defined without wraping the coordinates means bodies out of the (0,0,0) period can move realy fast. It has to be compensated properly in the definition of relative velocities (see Ig2 functors and contact laws).
 		//Reflect mean-field (periodic cell) acceleration in the velocity
 	if(scene->isPeriodic && homoDeform) {Vector3r dVel=dVelGrad*state->pos; state->vel+=dVel;}
-	if (!bodySelected || scene->selectedBody!=id) state->pos+=state->vel*dt;
+	state->pos+=state->vel*dt;
 }
 
 void NewtonIntegrator::leapfrogSphericalRotate(State* state, const Body::id_t& id, const Real& dt )

=== modified file 'pkg/dem/NormalInelasticityLaw.cpp'
--- pkg/dem/NormalInelasticityLaw.cpp	2012-01-23 14:43:54 +0000
+++ pkg/dem/NormalInelasticityLaw.cpp	2014-02-03 11:21:42 +0000
@@ -41,7 +41,7 @@
 // Check if there is a real overlap or not. The Ig2... seems to let exist interactions with negative un (= no overlap). Such interactions seem then to have to be deleted here.
         if (   un < 0      )
         {
-		 scene->interactions->requestErase(contact->getId1(),contact->getId2());// this, among other things, resets the interaction : geometry and physics variables (as forces, ...) are reset to defaut values
+		 scene->interactions->requestErase(contact);// this, among other things, resets the interaction : geometry and physics variables (as forces, ...) are reset to defaut values
 		 return;
         }
 

=== modified file 'pkg/dem/Polyhedra.hpp'
--- pkg/dem/Polyhedra.hpp	2013-10-16 15:24:49 +0000
+++ pkg/dem/Polyhedra.hpp	2014-01-28 08:43:35 +0000
@@ -93,6 +93,7 @@
 			.def("GetInertia",&Polyhedra::GetInertia,"return polyhedra's inertia tensor")
 			.def("GetOri",&Polyhedra::GetOri,"return polyhedra's orientation")
 			.def("GetCentroid",&Polyhedra::GetCentroid,"return polyhedra's centroid")
+			.def("GetSurfaceTriangulation",&Polyhedra::GetSurfaceTriangulation,"triangulation of facets (for plotting)")
 		);		
 		REGISTER_CLASS_INDEX(Polyhedra,Shape);
 };

=== added file 'pkg/dem/RungeKuttaCashKarp54Integrator.cpp'
--- pkg/dem/RungeKuttaCashKarp54Integrator.cpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/RungeKuttaCashKarp54Integrator.cpp	2014-02-17 14:31:35 +0000
@@ -0,0 +1,33 @@
+#include<yade/pkg/dem/RungeKuttaCashKarp54Integrator.hpp>
+#include<yade/core/Scene.hpp>
+
+YADE_PLUGIN((RungeKuttaCashKarp54Integrator));
+
+shared_ptr<Integrator> RungeKuttaCashKarp54Integrator_ctor_list(const python::list& slaves){ shared_ptr<Integrator> instance(new RungeKuttaCashKarp54Integrator); instance->slaves_set(slaves); return instance; }
+
+void RungeKuttaCashKarp54Integrator::action()
+{
+
+	Real dt=scene->dt;
+
+	Real time=scene->time;
+
+	error_checker_type rungekuttaerrorcontroller=error_checker_type(abs_err,rel_err,a_x,a_dxdt);
+	
+	controlled_stepper_type rungekuttastepper=controlled_stepper_type(rungekuttaerrorcontroller);
+
+	stateVector currentstates=getCurrentStates();
+	
+	resetstate.reserve(currentstates.size());
+	
+	copy(currentstates.begin(),currentstates.end(),back_inserter(resetstate));//copy current state to resetstate
+
+	this->timeresetvalue=time; //set reset time to the time just before the integration
+	
+	/*Try an adaptive integration*/
+
+	integrationsteps+=integrate_adaptive(rungekuttastepper,make_ode_wrapper( *((Integrator*)this) , &Integrator::system ),currentstates,time,time+dt, stepsize, observer(this));
+
+	scene->time=scene->time-dt;//Scene move next time step function already increments the time so we have to decrement it just before it.
+}
+

=== added file 'pkg/dem/RungeKuttaCashKarp54Integrator.hpp'
--- pkg/dem/RungeKuttaCashKarp54Integrator.hpp	1970-01-01 00:00:00 +0000
+++ pkg/dem/RungeKuttaCashKarp54Integrator.hpp	2014-02-17 14:31:35 +0000
@@ -0,0 +1,50 @@
+#pragma once
+#include <yade/core/Scene.hpp>
+#include<yade/pkg/dem/Integrator.hpp>
+#include<boost/numeric/odeint.hpp>
+
+
+typedef boost::numeric::odeint::runge_kutta_cash_karp54< stateVector > error_stepper_type; //Runge-Kutta 54 error stepper other steppers can also be used
+
+typedef boost::numeric::odeint::controlled_runge_kutta< error_stepper_type > controlled_stepper_type;//Controlled Runge Kutta stepper
+
+typedef boost::numeric::odeint::default_error_checker< error_stepper_type::value_type,error_stepper_type::algebra_type ,error_stepper_type::operations_type > error_checker_type; //Error checker type that is redefined for initialization using different tolerance values
+
+
+shared_ptr<Integrator> RungeKuttaCashKarp54Integrator_ctor_list(const python::list& slaves);
+class RungeKuttaCashKarp54Integrator: public Integrator {
+	
+	public:
+	
+		error_checker_type rungekuttaerrorcontroller;
+	
+		controlled_stepper_type rungekuttastepper;
+
+		void init()
+		{
+			rungekuttaerrorcontroller=error_checker_type(abs_err,rel_err,a_x,a_dxdt);
+			rungekuttastepper=controlled_stepper_type(rungekuttaerrorcontroller);
+		}
+
+
+
+		virtual void action();
+
+		YADE_CLASS_BASE_DOC_ATTRS_CTOR_PY(RungeKuttaCashKarp54Integrator,Integrator,"RungeKuttaCashKarp54Integrator engine.",
+		((Real,abs_err,1e-6,,"Relative integration tolerance"))
+		((Real,rel_err,1e-6,,"Absolute integration tolerance"))		
+		((Real,a_x,1.0,,""))
+		((Real,a_dxdt,1.0,,""))
+		((Real,stepsize,1e-6,,"It is not important for an adaptive integration but important for the observer for setting the found states after integration"))
+		,
+		/*ctor*/
+		init();
+		,
+		.def("__init__",python::make_constructor(RungeKuttaCashKarp54Integrator_ctor_list),"Construct from (possibly nested) list of slaves.")
+		/*py*/
+	);
+};
+REGISTER_SERIALIZABLE(RungeKuttaCashKarp54Integrator);
+
+
+

=== modified file 'pkg/dem/VTKRecorder.hpp'
--- pkg/dem/VTKRecorder.hpp	2013-11-05 10:52:25 +0000
+++ pkg/dem/VTKRecorder.hpp	2014-01-16 14:57:09 +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_ScGeom_CpmPhys_Cpm>`: ``cpmDamage`` (normalized residual strength averaged on particle), ``cpmStress`` (stress on particle); ``intr`` is activated automatically by ``cpm``\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\t``jcfpm``\n\t\tSaves data pertaining to the :yref:`rock (smooth)-jointed model<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM>`: ``damage`` is defined by :yref:`JCFpmState.tensBreak` + :yref:`JCFpmState.shearBreak`; ``intr`` is activated automatically by ``jcfpm``, and :yref:`on joint<JCFpmPhys.isOnJoint>` or :yref:`cohesive<JCFpmPhys.isCohesive>` interactions can be vizualized.\n\t``cracks``\n\t\tSaves other data pertaining to the :yref:`rock model<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM>`: ``cracks`` shows locations where cohesive bonds failed during the simulation, with their types (0/1  for tensile/shear breakages), their sizes (0.5*(R1+R2)), and their normal directions. The :yref:`corresponding attribute<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM.recordCracks>` has to be activated, and Key attributes have to be consistent.\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\t``pericell``\n\t\tSaves the shape of the cell (simulation has to be periodic).\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``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\t``jcfpm``\n\t\tSaves data pertaining to the :yref:`rock (smooth)-jointed model<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM>`: ``damage`` is defined by :yref:`JCFpmState.tensBreak` + :yref:`JCFpmState.shearBreak`; ``intr`` is activated automatically by ``jcfpm``, and :yref:`on joint<JCFpmPhys.isOnJoint>` or :yref:`cohesive<JCFpmPhys.isCohesive>` interactions can be vizualized.\n\t``cracks``\n\t\tSaves other data pertaining to the :yref:`rock model<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM>`: ``cracks`` shows locations where cohesive bonds failed during the simulation, with their types (0/1  for tensile/shear breakages), their sizes (0.5*(R1+R2)), and their normal directions. The :yref:`corresponding attribute<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM.recordCracks>` has to be activated, and Key attributes have to be consistent.\n\n"))
 		((string,Key,"",,"Necessary if :yref:`recorders<VTKRecorder.recorders>` contains 'cracks'. A string specifying the name of file 'cracks___.txt' that is considered in this case (see :yref:`corresponding attribute<Law2_ScGeom_JCFpmPhys_JointedCohesiveFrictionalPM.Key>`)."))
 		((int,mask,0,,"If mask defined, only bodies with corresponding groupMask will be exported. If 0, all bodies will be exported.")),
 		/*ctor*/

=== modified file 'pkg/dem/ViscoelasticCapillarPM.cpp'
--- pkg/dem/ViscoelasticCapillarPM.cpp	2013-08-28 12:00:42 +0000
+++ pkg/dem/ViscoelasticCapillarPM.cpp	2014-01-30 08:09:44 +0000
@@ -15,7 +15,7 @@
     * 
     */
      
-  if (phys.CapillarType  == "Weigert") {
+  if (phys.CapillarType == Weigert) {
       /* Capillar model from [Weigert1999]
        */
         Real R = phys.R;
@@ -44,7 +44,7 @@
         fC = M_PI/4.0*pow((2.0*R),2.0)*pow(sin(beta),2.0)*Pk +
              phys.gamma*M_PI*2.0*R*sin(beta)*sin(beta+phys.theta);                                // [Weigert1999], equation (21)
         
-      } else if (phys.CapillarType  == "Willett_numeric") {
+      } else if (phys.CapillarType == Willett_numeric) {
       
         /* Capillar model from [Willett2000]
          */ 
@@ -85,7 +85,7 @@
         Real FS = exp(lnFS);
         
         fC = FS * 2.0 * M_PI* R * Gamma;
-      } else if (phys.CapillarType  == "Willett_analytic") {
+      } else if (phys.CapillarType == Willett_analytic) {
         /* Capillar model from Willet [Willett2000] (analytical solution), but 
          * used also in the work of Herminghaus [Herminghaus2005]
          */
@@ -106,27 +106,36 @@
         Real f_star = cos(phys.theta)/(1 + 2.1*sPl + 10.0 * pow(sPl, 2.0));                 // [Willett2000], equation (12)
         fC = f_star * (2*M_PI*R*Gamma);                                                     // [Willett2000], equation (13), against F
         
-      } else if (phys.CapillarType  == "Rabinovich") {
-        /* Capillar model from Rabinovich [Rabinov2005]
+      } else if ((phys.CapillarType  == Rabinovich) or (phys.CapillarType  == Lambert)) {
+        /* 
+         * Capillar model from Rabinovich [Rabinov2005]
+         *
+         * This formulation from Rabinovich has been later verified and corrected
+         * by Lambert [Lambert2008]. So we can calculate both formulations
+         * 
          */
-         
+           
         Real R = phys.R;
         Real Gamma = phys.gamma;
         Real H = -geom.penetrationDepth;
         Real V = phys.Vb;
         
-        Real alpha = 0.0;
         Real dsp = 0.0;
         if (H!=0.0) {
-          alpha = sqrt(H/R*(-1+ sqrt(1 + 2.0*V/(M_PI*R*H*H))));                          // [Rabinov2005], equation (A3)
-        
-          dsp = H/2.0*(-1.0 + sqrt(1.0 + 2.0*V/(M_PI*R*H*H)));                           // [Rabinov2005], equation (20)
-        
-          fC = -(2*M_PI*R*Gamma*cos(phys.theta))/(1+(H/(2*dsp))) - 
-              2*M_PI*R*Gamma*sin(alpha)*sin(phys.theta + alpha);                         // [Rabinov2005], equation (19)
+          dsp = H/2.0*(-1.0 + sqrt(1.0 + 2.0*V/(M_PI*R*H*H)));                            // [Rabinov2005], equation (20)
+          fC = -(2*M_PI*R*Gamma*cos(phys.theta))/(1+(H/(2*dsp)));                         // [Lambert2008], equation (65), taken from [Rabinov2005]
+          
+          if (phys.CapillarType  == Rabinovich) {
+            const Real alpha = sqrt(H/R*(-1+ sqrt(1 + 2.0*V/(M_PI*R*H*H))));              // [Rabinov2005], equation (A3)
+            fC -= 2*M_PI*R*Gamma*sin(alpha)*sin(phys.theta + alpha);                      // [Rabinov2005], equation (19)
+          }
         } else {
-          fC = -(2*M_PI*R*Gamma*cos(phys.theta)) - 
-              2*M_PI*R*Gamma*sin(alpha)*sin(phys.theta + alpha);                         // [Rabinov2005], equation (19)
+          fC = -(2*M_PI*R*Gamma*cos(phys.theta));
+          
+          if (phys.CapillarType == Rabinovich) {
+            const Real alpha = 0.0;
+            fC -= 2*M_PI*R*Gamma*sin(alpha)*sin(phys.theta + alpha);                      // [Rabinov2005], equation (19)
+          }
         }
         
         fC *=-1;

=== modified file 'pkg/dem/ViscoelasticPM.cpp'
--- pkg/dem/ViscoelasticPM.cpp	2013-08-28 13:31:12 +0000
+++ pkg/dem/ViscoelasticPM.cpp	2014-02-07 18:20:02 +0000
@@ -14,8 +14,22 @@
 /* ViscElPhys */
 ViscElPhys::~ViscElPhys(){}
 
+/* Contact parameter calculation function */
+Real Ip2_ViscElMat_ViscElMat_ViscElPhys::contactParameterCalculation(const Real& l1, const Real& l2, const bool& massMultiply){
+	if (massMultiply) {
+		// If one of paramaters > 0. we DO NOT return 0
+    Real a = (l1?1/l1:0) + (l2?1/l2:0);
+    if (a) return 1/a;
+    else return 0;
+	} else {
+		// If one of paramaters > 0, we return 0
+		return (l1>0 or l2>0)?l1*l2/(l1+l2):0;
+	}
+}
+
 /* Ip2_ViscElMat_ViscElMat_ViscElPhys */
 void Ip2_ViscElMat_ViscElMat_ViscElPhys::go(const shared_ptr<Material>& b1, const shared_ptr<Material>& b2, const shared_ptr<Interaction>& interaction) {
+
 	// no updates of an existing contact 
 	if(interaction->phys) return;
 	ViscElMat* mat1 = static_cast<ViscElMat*>(b1.get());
@@ -26,37 +40,43 @@
 	if (mat1->massMultiply and mat2->massMultiply) {
 		mass1 = Body::byId(interaction->getId1())->state->mass;
 		mass2 = Body::byId(interaction->getId2())->state->mass;
+		if (mass1 == 0.0 and mass2 > 0.0) {
+			mass1 = mass2;
+		} else if (mass2 == 0.0 and mass1 > 0.0) {
+			mass2 = mass1;
+		}
 	}
 	
-	const Real kn1 = mat1->kn*mass1; const Real cn1 = mat1->cn*mass1;
-	const Real ks1 = mat1->ks*mass1; const Real cs1 = mat1->cs*mass1;
+	GenericSpheresContact* sphCont=YADE_CAST<GenericSpheresContact*>(interaction->geom.get());
+	Real R1=sphCont->refR1>0?sphCont->refR1:sphCont->refR2;
+	Real R2=sphCont->refR2>0?sphCont->refR2:sphCont->refR1;
+	
+	const Real kn1 = isnan(mat1->kn)?2*mat1->young*R1:mat1->kn*mass1;
+	const Real cn1 = mat1->cn*mass1;
+	const Real ks1 = isnan(mat1->ks)?kn1*mat1->poisson:mat1->ks*mass1;
+	const Real cs1 = mat1->cs*mass1;
+	
 	const Real mR1 = mat1->mR;      const Real mR2 = mat2->mR; 
 	const int mRtype1 = mat1->mRtype; const int mRtype2 = mat2->mRtype;
-	const Real kn2 = mat2->kn*mass2; const Real cn2 = mat2->cn*mass2;
-	const Real ks2 = mat2->ks*mass2; const Real cs2 = mat2->cs*mass2;
+	
+	const Real kn2 = isnan(mat2->kn)?2*mat2->young*R2:mat2->kn*mass2;
+	const Real cn2 = mat2->cn*mass2;
+	const Real ks2 = isnan(mat2->ks)?kn2*mat2->poisson:mat2->ks*mass2;
+	const Real cs2 = mat2->cs*mass2;
 		
 	ViscElPhys* phys = new ViscElPhys();
-	
-	if ((kn1>0) or (kn2>0)) {
-		phys->kn = 1/( ((kn1>0)?1/kn1:0) + ((kn2>0)?1/kn2:0) );
-	} else {
-		phys->kn = 0;
-	}
-	if ((ks1>0) or (ks2>0)) {
-		phys->ks = 1/( ((ks1>0)?1/ks1:0) + ((ks2>0)?1/ks2:0) );
-	} else {
-		phys->ks = 0;
-	} 
-	
-  if ((mR1>0) or (mR2>0)) {
+
+	phys->kn = contactParameterCalculation(kn1,kn2, mat1->massMultiply&&mat2->massMultiply);
+	phys->ks = contactParameterCalculation(ks1,ks2, mat1->massMultiply&&mat2->massMultiply);
+	phys->cn = contactParameterCalculation(cn1,cn2, mat1->massMultiply&&mat2->massMultiply);
+	phys->cs = contactParameterCalculation(cs1,cs2, mat1->massMultiply&&mat2->massMultiply);
+
+ 	if ((mR1>0) or (mR2>0)) {
 		phys->mR = 2.0/( ((mR1>0)?1/mR1:0) + ((mR2>0)?1/mR2:0) );
 	} else {
 		phys->mR = 0;
 	}
-  
-	phys->cn = (cn1?1/cn1:0) + (cn2?1/cn2:0); phys->cn = phys->cn?1/phys->cn:0;
-	phys->cs = (cs1?1/cs1:0) + (cs2?1/cs2:0); phys->cs = phys->cs?1/phys->cs:0;
-  
+
 	phys->tangensOfFrictionAngle = std::tan(std::min(mat1->frictionAngle, mat2->frictionAngle)); 
 	phys->shearForce = Vector3r(0,0,0);
 	
@@ -84,8 +104,15 @@
 		} else {
 			throw runtime_error("Theta should be equal for both particles!.");
 		}
+		
 		if (mat1->CapillarType == mat2->CapillarType and mat2->CapillarType != ""){
-			phys->CapillarType = mat1->CapillarType;
+			
+			if      (mat1->CapillarType == "Willett_numeric")  phys->CapillarType = Willett_numeric;
+			else if (mat1->CapillarType == "Willett_analytic") phys->CapillarType = Willett_analytic;
+			else if (mat1->CapillarType == "Weigert")          phys->CapillarType = Weigert;
+			else if (mat1->CapillarType == "Rabinovich")       phys->CapillarType = Rabinovich;
+			else if (mat1->CapillarType == "Lambert")          phys->CapillarType = Lambert;
+			else                                               phys->CapillarType = None_Capillar;
 		} else {
 			throw runtime_error("CapillarType should be equal for both particles!.");
 		}
@@ -171,8 +198,16 @@
 	shearForce += phys.ks*dt*shearVelocity; // the elastic shear force have a history, but
 	Vector3r shearForceVisc = Vector3r::Zero(); // the viscous shear damping haven't a history because it is a function of the instant velocity 
 
-	phys.normalForce = ( phys.kn * geom.penetrationDepth + phys.cn * normalVelocity ) * geom.normal;
 
+	// Prevent appearing of attraction forces due to a viscous component
+	// [Radjai2011], page 3, equation [1.7]
+	// [Schwager2007]
+	const Real normForceReal = phys.kn * geom.penetrationDepth + phys.cn * normalVelocity;
+	if (normForceReal < 0) {
+		phys.normalForce = Vector3r::Zero();
+	} else {
+		phys.normalForce = normForceReal * geom.normal;
+	}
 	
 	Vector3r momentResistance = Vector3r::Zero();
 	if (phys.mR>0.0) {
@@ -209,3 +244,4 @@
 		addTorque(id2, c2x.cross(f)-momentResistance,scene);
   }
 }
+

=== modified file 'pkg/dem/ViscoelasticPM.hpp'
--- pkg/dem/ViscoelasticPM.hpp	2013-08-28 12:00:42 +0000
+++ pkg/dem/ViscoelasticPM.hpp	2014-01-30 08:09:44 +0000
@@ -4,24 +4,24 @@
 
 #pragma once
 
-#include<yade/core/Material.hpp>
+#include<yade/pkg/common/ElastMat.hpp>
 #include<yade/pkg/dem/FrictPhys.hpp>
 #include<yade/pkg/common/Dispatching.hpp>
 #include<yade/pkg/dem/ScGeom.hpp>
+#include<yade/pkg/dem/DemXDofGeom.hpp>
 
 /* Simple viscoelastic model */
 
 /// Material
 /// Note: Shop::getViscoelasticFromSpheresInteraction can get kn,cn,ks,cs from a analytical solution of a pair spheres interaction problem.
-class ViscElMat : public Material {
+class ViscElMat : public FrictMat {
 	public:
 		virtual ~ViscElMat();
-	YADE_CLASS_BASE_DOC_ATTRS_CTOR(ViscElMat,Material,"Material for simple viscoelastic model of contact.\n\n.. note::\n\t ``Shop::getViscoelasticFromSpheresInteraction`` (and :yref:`yade.utils.getViscoelasticFromSpheresInteraction` in python) compute :yref:`kn<ViscElMat::kn>`, :yref:`cn<ViscElMat::cn>`,  :yref:`ks<ViscElMat::ks>`,  :yref:`cs<ViscElMat::cs>` from analytical solution of a pair spheres interaction problem.",
+	YADE_CLASS_BASE_DOC_ATTRS_CTOR(ViscElMat,FrictMat,"Material for simple viscoelastic model of contact.\n\n.. note::\n\t ``Shop::getViscoelasticFromSpheresInteraction`` (and :yref:`yade.utils.getViscoelasticFromSpheresInteraction` in python) compute :yref:`kn<ViscElMat::kn>`, :yref:`cn<ViscElMat::cn>`,  :yref:`ks<ViscElMat::ks>`,  :yref:`cs<ViscElMat::cs>` from analytical solution of a pair spheres interaction problem.",
 		((Real,kn,NaN,,"Normal elastic stiffness"))
 		((Real,cn,NaN,,"Normal viscous constant"))
 		((Real,ks,NaN,,"Shear elastic stiffness"))
 		((Real,cs,NaN,,"Shear viscous constant"))
-		((Real,frictionAngle,NaN,,"Friction angle [rad]"))
 		((bool,massMultiply,true,,"Stiffness and viscosity are multiplied by the reduced mass. If massMultiply=false, these parameter are set explicitly without mass multiplication"))
 		((Real,mR,0.0,,"Rolling resistance, see [Zhou1999536]_."))
 		((unsigned int,mRtype,1,,"Rolling resistance type, see [Zhou1999536]_. mRtype=1 - equation (3) in [Zhou1999536]_; mRtype=2 - equation (4) in [Zhou1999536]_."))
@@ -29,14 +29,15 @@
 		((Real,Vb,NaN,,"Liquid bridge volume [m^3]"))
 		((Real,gamma,NaN,,"Surface tension [N/m]"))
 		((Real,theta,NaN,,"Contact angle [°]"))
-		((std::string,CapillarType,"",,"Different types of capillar interaction: Willett_numeric, Willett_analytic [Willett2000]_ , Weigert [Weigert1999]_ , Rabinovich [Rabinov2005]_ ")),
+		((std::string,CapillarType,"",,"Different types of capillar interaction: Willett_numeric, Willett_analytic [Willett2000]_ , Weigert [Weigert1999]_ , Rabinovich [Rabinov2005]_ , Lambert (simplified, corrected Rabinovich model) [Lambert2008]_ ")),
 		createIndex();
 	);
-	REGISTER_CLASS_INDEX(ViscElMat,Material);
+	REGISTER_CLASS_INDEX(ViscElMat,FrictMat);
 };
 REGISTER_SERIALIZABLE(ViscElMat);
 
 /// Interaction physics
+enum CapType {None_Capillar, Willett_numeric, Willett_analytic, Weigert, Rabinovich, Lambert};
 class ViscElPhys : public FrictPhys{
 	public:
 		virtual ~ViscElPhys();
@@ -52,9 +53,10 @@
 		((Real,Vb,NaN,,"Liquid bridge volume [m^3]"))
 		((Real,gamma,NaN,,"Surface tension [N/m]"))
 		((Real,theta,NaN,,"Contact angle [rad]"))
-		((std::string,CapillarType,"",,"Different types of capillar interaction: Willett_numeric, Willett_analytic, Weigert, Rabinovich")),
+		((CapType,CapillarType,None_Capillar,,"Different types of capillar interaction: Willett_numeric, Willett_analytic, Weigert, Rabinovich, Lambert")),
 		createIndex();
 	)
+	REGISTER_CLASS_INDEX(ViscElPhys,FrictPhys);
 };
 REGISTER_SERIALIZABLE(ViscElPhys);
 
@@ -65,6 +67,8 @@
 		virtual void go(const shared_ptr<Material>& b1,
 					const shared_ptr<Material>& b2,
 					const shared_ptr<Interaction>& interaction);
+	private :
+		Real contactParameterCalculation(const Real& l1,const Real& l2, const bool& massMultiply);
 	YADE_CLASS_BASE_DOC(Ip2_ViscElMat_ViscElMat_ViscElPhys,IPhysFunctor,"Convert 2 instances of :yref:`ViscElMat` to :yref:`ViscElPhys` using the rule of consecutive connection.");
 	FUNCTOR2D(ViscElMat,ViscElMat);
 
@@ -78,7 +82,9 @@
 		virtual void go(shared_ptr<IGeom>&, shared_ptr<IPhys>&, Interaction*);
 	private:
 		Real calculateCapillarForce(const ScGeom& geom, ViscElPhys& phys);
+	public :
 	FUNCTOR2D(ScGeom,ViscElPhys);
 	YADE_CLASS_BASE_DOC(Law2_ScGeom_ViscElPhys_Basic,LawFunctor,"Linear viscoelastic model operating on :yref:`ScGeom` and :yref:`ViscElPhys`. The model is mostly based on the paper for For details see Pournin [Pournin2001]_ .");
+	DECLARE_LOGGER;
 };
 REGISTER_SERIALIZABLE(Law2_ScGeom_ViscElPhys_Basic);

=== modified file 'py/_extraDocs.py'
--- py/_extraDocs.py	2013-09-19 08:50:04 +0000
+++ py/_extraDocs.py	2013-12-09 11:24:57 +0000
@@ -84,9 +84,9 @@
 wrapper.Peri3dController.__doc__=r'''
 Class for controlling independently all 6 components of "engineering" :yref:`stress<Peri3dController.stress>` and :yref:`strain<Peri3dController.strain>` of periodic :yref:`Cell`. :yref:`goal<Peri3dController.goal>` are the goal values, while :yref:`stressMask<Peri3dController.stressMask>` determines which components prescribe stress and which prescribe strain.
 
-If the strain is prescribed, appropeiate strain rate is directly applied. If the stress is prescribed, the strain predictor is used: from stress values in two previous steps the value of strain rate is prescribed so as the value of stress in the next step is as close as possible to the ideal one. Current algorithm is extremly simple and probably will be changed in future, but is roboust enough and mostly works fine.
+If the strain is prescribed, appropriate strain rate is directly applied. If the stress is prescribed, the strain predictor is used: from stress values in two previous steps the value of strain rate is prescribed so as the value of stress in the next step is as close as possible to the ideal one. Current algorithm is extremly simple and probably will be changed in future, but is roboust enough and mostly works fine.
 
-Stress error (difference between actual and ideal stress)  is evaluated in current and previous steps ($\mathrm{d}\sigma_i,\mathrm{d}\sigma_{i-1}$. Linear extrapolation is used to estimate error in the next step
+Stress error (difference between actual and ideal stress)  is evaluated in current and previous steps ($\mathrm{d}\sigma_i,\mathrm{d}\sigma_{i-1}$). Linear extrapolation is used to estimate error in the next step
 
 .. math:: \mathrm{d}\sigma_{i+1}=2\mathrm{d}\sigma_i - \mathrm{d}\sigma_{i-1}
 
@@ -106,7 +106,7 @@
 
 Current implementation allow user to define independent loading "path" for each prescribed component. i.e. define the prescribed value as a function of time (or :yref:`progress<Peri3dController.progress>` or steps). See :yref:`Paths<Peri3dController.xxPath>`.
 
-Examples :ysrc:`scripts/test/peri3dController_example1` and :ysrc:`scripts/test/peri3dController_triaxialCompression` explain usage and inputs of Peri3dController, :ysrc:`scripts/test/peri3dController_shear` is an example of using shear components and also simulation on rotatd cell.
+Examples :ysrc:`examples/test/peri3dController_example1.py` and :ysrc:`examples/test/peri3dController_triaxialCompression.py` explain usage and inputs of Peri3dController, :ysrc:`examples/test/peri3dController_shear.py` is an example of using shear components and also simulation on rotated cell.
 '''
 
 

=== modified file 'py/_utils.cpp'
--- py/_utils.cpp	2013-11-13 07:37:51 +0000
+++ py/_utils.cpp	2014-01-21 15:18:44 +0000
@@ -502,7 +502,7 @@
 	py::def("RayleighWaveTimeStep",RayleighWaveTimeStep,"Determination of time step according to Rayleigh wave speed of force propagation.");
 	py::def("getSpheresVolume",Shop__getSpheresVolume,(py::arg("mask")=-1),"Compute the total volume of spheres in the simulation (might crash for now if dynamic bodies are not spheres), mask parameter is considered");
 	py::def("getSpheresMass",Shop__getSpheresMass,(py::arg("mask")=-1),"Compute the total mass of spheres in the simulation (might crash for now if dynamic bodies are not spheres), mask parameter is considered");
-	py::def("porosity",Shop__getPorosity,(py::arg("volume")=-1),"Compute packing poro sity $\\frac{V-V_s}{V}$ where $V$ is overall volume and $V_s$ is volume of spheres.\n\n:param float volume: overall volume which must be specified for aperiodic simulations. For periodic simulations, current volume of the :yref:`Cell` is used.\n");
+	py::def("porosity",Shop__getPorosity,(py::arg("volume")=-1),"Compute packing porosity $\\frac{V-V_s}{V}$ where $V$ is overall volume and $V_s$ is volume of spheres.\n\n:param float volume: overall volume which must be specified for aperiodic simulations. For periodic simulations, current volume of the :yref:`Cell` is used.\n");
 	py::def("voxelPorosity",Shop__getVoxelPorosity,(py::arg("resolution")=200,py::arg("start")=Vector3r(0,0,0),py::arg("end")=Vector3r(0,0,0)),"Compute packing porosity $\\frac{V-V_v}{V}$ where $V$ is a specified volume (from start to end) and $V_v$ is volume of voxels that fall inside any sphere. The calculation method is to divide whole volume into a dense grid of voxels (at given resolution), and count the voxels that fall inside any of the spheres. This method allows one to calculate porosity in any given sub-volume of a whole sample. It is properly excluding part of a sphere that does not fall inside a specified volume.\n\n:param int resolution: voxel grid resolution, values bigger than resolution=1600 require a 64 bit operating system, because more than 4GB of RAM is used, a resolution=800 will use 500MB of RAM.\n:param Vector3 start: start corner of the volume.\n:param Vector3 end: end corner of the volume.\n");
 	py::def("aabbExtrema",aabbExtrema,(py::arg("cutoff")=0.0,py::arg("centers")=false),"Return coordinates of box enclosing all bodies\n\n:param bool centers: do not take sphere radii in account, only their centroids\n:param float∈〈0…1〉 cutoff: relative dimension by which the box will be cut away at its boundaries.\n\n\n:return: (lower corner, upper corner) as (Vector3,Vector3)\n\n");
 	py::def("ptInAABB",isInBB,"Return True/False whether the point p is within box given by its min and max corners");
@@ -537,7 +537,7 @@
 	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_{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("getStress",Shop::getStress,(py::args("volume")=0),"Compute and return Love-Weber stress tensor:\n\n $\\sigma_{ij}=\\frac{1}{V}\\sum_b f_i^b l_j^b$, where the sum is over all interactions, with $f$ the contact force and $l$ the branch vector (joining centers of the bodies). Stress is negativ for repulsive contact forces, i.e. compression. $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("getCapillaryStress",Shop::getCapillaryStress,(py::args("volume")=0),"Compute and return Love-Weber capillary stress tensor:\n\n $\\sigma^{cap}_{ij}=\\frac{1}{V}\\sum_b l_i^b f^{cap,b}_j$, where the sum is over all interactions, with $l$ the branch vector (joining centers of the bodies) and $f^{cap}$ is the capillary 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. Only the CapillaryPhys interaction type is supported presently.");
 	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.");

=== modified file 'py/export.py'
--- py/export.py	2013-11-04 14:20:24 +0000
+++ py/export.py	2014-02-17 16:37:16 +0000
@@ -7,13 +7,14 @@
 from yade import utils,Matrix3,Vector3
 
 #textExt===============================================================
-def textExt(filename, format='x_y_z_r', comment='',mask=-1):
+def textExt(filename, format='x_y_z_r', comment='',mask=-1,attrs=[]):
 	"""Save sphere coordinates and other parameters into a text file in specific format. Non-spherical bodies are silently skipped. Users can add here their own specific format, giving meaningful names. The first file row will contain the format name. Be sure to add the same format specification in ymport.textExt.
 
 	:param string filename: the name of the file, where sphere coordinates will be exported.
-	:param string format: the name of output format. Supported 'x_y_z_r'(default), 'x_y_z_r_matId'
-	:param string comment: the text, which will be added as a comment at the top of file. If you want to create several lines of text, please use '\\\\n#' for next lines.
+	:param string format: the name of output format. Supported 'x_y_z_r'(default), 'x_y_z_r_matId', 'x_y_z_r_attrs' (use proper comment)
+	:param string comment: the text, which will be added as a comment at the top of file. If you want to create several lines of text, please use '\\\\n#' for next lines. With 'x_y_z_r_attrs' format, the last (or only) line should consist of column headers of quantities passed as attrs (1 comment word for scalars, 3 comment words for vectors and 9 comment words for matrices)
 	:param int mask: export only spheres with the corresponding mask export only spheres with the corresponding mask
+	:param [str] attrs: attributes to be exported with 'x_y_z_r_attrs' format. Each str in the list is evaluated for every body exported with body=b (i.e. 'b.state.pos.norm()' would stand for distance of body from coordinate system origin)
 	:return: number of spheres which were written.
 	:rtype: int
 	"""
@@ -26,12 +27,19 @@
 	
 	count=0
 	
+	# TODO use output=[] instrad of ''???
 	output = ''
 	outputVel=''
 	if (format<>'liggghts_in'):
 		output = '#format ' + format + '\n'
 		if (comment):
-			output += '# ' + comment + '\n'
+			if format=='x_y_z_r_attrs':
+				cmts = comment.split('\n')
+				for cmt in cmts[:-1]:
+					output += cmt
+				output += '# x y z r ' + cmts[-1] + '\n'
+			else:
+				output += '# ' + comment + '\n'
 	
 	minCoord= Vector3.Zero
 	maxCoord= Vector3.Zero
@@ -44,6 +52,17 @@
 					output+=('%g\t%g\t%g\t%g\n'%(b.state.pos[0],b.state.pos[1],b.state.pos[2],b.shape.radius))
 				elif (format=='x_y_z_r_matId'):
 					output+=('%g\t%g\t%g\t%g\t%d\n'%(b.state.pos[0],b.state.pos[1],b.state.pos[2],b.shape.radius,b.material.id))
+				elif (format=='x_y_z_r_attrs'):
+					output+=('%g\t%g\t%g\t%g'%(b.state.pos[0],b.state.pos[1],b.state.pos[2],b.shape.radius))
+					for cmd in attrs:
+						v = eval(cmd)
+						if isinstance(v,(int,float)):
+							output+='\t%g'%v
+						elif isinstance(v,Vector3):
+							output+='\t%g\t%g\t%g'%tuple(v[i] for i in xrange(3))
+						elif isinstance(v,Matrix3):
+							output+='\t%g'%tuple(v[i] for i in xrange(9))
+					output += '\n'
 				elif (format=='id_x_y_z_r_matId'):
 					output+=('%d\t%g\t%g\t%g\t%g\t%d\n'%(b.id,b.state.pos[0],b.state.pos[1],b.state.pos[2],b.shape.radius,b.material.id))
 				elif (format=='jointedPM'):
@@ -76,6 +95,74 @@
 	out.close()
 	return count
 
+	bodies = [b for b in O.bodies if isinstance(b.shape,Sphere) and (True if mask==-1 else b.msak==mask)]
+	data = []
+	for b in bodies:
+		pos = b.state.pos
+		d = [pos[i] for i in (0,1,2)]
+		for name,command in what:
+			val = eval(command)
+			if isinstance(val,Matrix3):
+				d.extend((val[0,0],val[0,1],val[0,2],val[1,0],val[1,1],val[1,2],val[2,0],val[2,1],val[2,2]))
+			elif isinstance(val,Vector3):
+				d.extend((v[0],v[1],v[2]))
+			elif isinstance(val,(int,float)):
+				d.append(val)
+			else:
+				print 'WARNING: export.text: wrong `what` parameter, output might be corrupted'
+				return 0
+		data.append(d)
+	dataw = [' '.join('%e'%v for v in d) for d in data]
+	outFile = open(filename,'w')
+	outFile.writelines(dataw)
+	outFile.close()
+	return len(bodies)
+  
+#textExt===============================================================
+def textClumps(filename, format='x_y_z_r_clumpId', comment='',mask=-1):
+	"""Save clumps-members into a text file. Non-clumps members are bodies are silently skipped.
+
+	:param string filename: the name of the file, where sphere coordinates will be exported.
+	:param string comment: the text, which will be added as a comment at the top of file. If you want to create several lines of text, please use '\\\\n#' for next lines.
+	:param int mask: export only spheres with the corresponding mask export only spheres with the corresponding mask
+	:return: number of clumps, number of spheres which were written.
+	:rtype: int
+	"""
+	O=Omega()
+	
+	try:
+		out=open(filename,'w')
+	except:
+		raise RuntimeError("Problem to write into the file")
+	
+	count=0
+	countClumps=0
+	output = ''
+	output = '#format x_y_z_r_clumpId\n'
+	if (comment):
+		output += '# ' + comment + '\n'
+	
+	minCoord= Vector3.Zero
+	maxCoord= Vector3.Zero
+	maskNumber = []
+	
+	for bC in O.bodies:
+		if bC.isClump:
+			keys = bC.shape.members.keys()
+			countClumps+=1
+			for ii in keys:
+				try:
+					b = O.bodies[ii]
+					if (isinstance(b.shape,Sphere) and ((mask<0) or ((mask&b.mask)>0))):
+						output+=('%g\t%g\t%g\t%g\t%g\n'%(b.state.pos[0],b.state.pos[1],b.state.pos[2],b.shape.radius,bC.id))
+						count+=1
+				except AttributeError:
+					pass
+			
+	out.write(output)
+	out.close()
+	return countClumps,count
+
 #VTKWriter===============================================================
 class VTKWriter:
 	"""
@@ -225,6 +312,7 @@
 		self.spheresSnapCount = startSnap
 		self.facetsSnapCount = startSnap
 		self.intrsSnapCount = startSnap
+		self.polyhedraSnapCount = startSnap
 		self.baseName = baseName
 
 	def exportSpheres(self,ids='all',what=[],comment="comment",numLabel=None,useRef=False):
@@ -232,7 +320,7 @@
 
 		:param ids: if "all", then export all spheres, otherwise only spheres from integer list
 		:type ids: [int] | "all"
-		:param what: what other than then position and radius export. parameter is list of couple (name,command). Name is string under which it is save to vtk, command is string to evaluate. Node that the bodies are labeled as b in this function. Scalar, vector and tensor variables are supported. For example, to export velocity (with name particleVelocity) and the distance form point (0,0,0) (named as dist) you should write: ... what=[('particleVelocity','b.state.vel'),('dist','b.state.pos.norm()', ...
+		:param what: what other than then position and radius export. parameter is list of couple (name,command). Name is string under which it is save to vtk, command is string to evaluate. Note that the bodies are labeled as b in this function. Scalar, vector and tensor variables are supported. For example, to export velocity (with name particleVelocity) and the distance form point (0,0,0) (named as dist) you should write: ... what=[('particleVelocity','b.state.vel'),('dist','b.state.pos.norm()', ...
 		:type what: [tuple(2)]
 		:param string comment: comment to add to vtk file
 		:param int numLabel: number of file (e.g. time step), if unspecified, the last used value + 1 will be used
@@ -420,7 +508,7 @@
 
 		:param ids: if "all", then export all spheres, otherwise only spheres from integer list
 		:type ids: [int] | "all"
-		:param what: what to export. parameter is list of couple (name,command). Name is string under which it is save to vtk, command is string to evaluate. Node that the interactions are labeled as i in this function. Scalar, vector and tensor variables are supported. For example, to export stiffness difference from certain value (1e9) (named as dStiff) you should write: ... what=[('dStiff','i.phys.kn-1e9'), ...
+		:param what: what to export. parameter is list of couple (name,command). Name is string under which it is save to vtk, command is string to evaluate. Note that the interactions are labeled as i in this function. Scalar, vector and tensor variables are supported. For example, to export stiffness difference from certain value (1e9) (named as dStiff) you should write: ... what=[('dStiff','i.phys.kn-1e9'), ...
 		:type what: [tuple(2)]
 		:param string comment: comment to add to vtk file
 		:param int numLabel: number of file (e.g. time step), if unspecified, the last used value + 1 will be used
@@ -442,29 +530,31 @@
 		for j,i in enumerate(intrs):
 			outFile.write("2 %d %d\n"%(i[0]+1,i[1]+1))
 		outFile.write("\nCELL_DATA %d\n"%(n))
+		i = None
 		for i in O.interactions:
 			if i.isReal: break
-		for name,command in what:
-			test = eval(command)
-			if isinstance(test,Matrix3):
-				print 'WARNING: export.VTKExporter.exportInteractions: wrong `what` parameter, Matrix3 output not (yet?) supported'
-				#outFile.write("\nTENSORS %s double\n"%(name))
-				#for i in intrs:
-				#	t = eval(command)
-				#	outFile.write("%g %g %g\n%g %g %g\n%g %g %g\n\n"%(t[0,0],t[0,1],t[0,2],t[1,0],t[1,1],t[1,2],t[2,0],t[2,1],t[2,2]))
-			elif isinstance(test,Vector3):
-				print 'WARNING: export.VTKExporter.exportInteractions: wrong `what` parameter, Vector3 output not (yet?) supported'
-				#outFile.write("\nVECTORS %s double\n"%(name))
-				#for i in intrs:
-				#	v = eval(command)
-				#	outFile.write("%g %g %g\n"%(v[0],v[1],v[2]))
-			elif isinstance(test,(int,float)):
-				outFile.write("\nSCALARS %s double 1\nLOOKUP_TABLE default\n"%(name))
-				for ii,jj in ids:
-					i = O.interactions[ii,jj]
-					outFile.write("%g\n"%(eval(command)))
-			else:
-				print 'WARNING: export.VTKExporter.exportInteractions: wrong `what` parameter, vtk output might be corrupted'
+		if i:
+			for name,command in what:
+				test = eval(command)
+				if isinstance(test,Matrix3):
+					print 'WARNING: export.VTKExporter.exportInteractions: wrong `what` parameter, Matrix3 output not (yet?) supported'
+					#outFile.write("\nTENSORS %s double\n"%(name))
+					#for i in intrs:
+					#	t = eval(command)
+					#	outFile.write("%g %g %g\n%g %g %g\n%g %g %g\n\n"%(t[0,0],t[0,1],t[0,2],t[1,0],t[1,1],t[1,2],t[2,0],t[2,1],t[2,2]))
+				elif isinstance(test,Vector3):
+					print 'WARNING: export.VTKExporter.exportInteractions: wrong `what` parameter, Vector3 output not (yet?) supported'
+					#outFile.write("\nVECTORS %s double\n"%(name))
+					#for i in intrs:
+					#	v = eval(command)
+					#	outFile.write("%g %g %g\n"%(v[0],v[1],v[2]))
+				elif isinstance(test,(int,float)):
+					outFile.write("\nSCALARS %s double 1\nLOOKUP_TABLE default\n"%(name))
+					for ii,jj in ids:
+						i = O.interactions[ii,jj]
+						outFile.write("%g\n"%(eval(command)))
+				else:
+					print 'WARNING: export.VTKExporter.exportInteractions: wrong `what` parameter, vtk output might be corrupted'
 		if verticesWhat:
 			outFile.write("\nPOINT_DATA %d\n"%(2*n))
 			b = b1 = b2 = O.bodies[0]
@@ -553,6 +643,84 @@
 		outFile.write('\nCELL_TYPES 1\n12\n')
 		outFile.close()
 
+	def exportPolyhedra(self,ids='all',what=[],comment="comment",numLabel=None):
+		"""Exports polyhedrons and defined properties.
+
+		:param ids: if "all", then export all polyhedrons, otherwise only polyhedrons from integer list
+		:type ids: [int] | "all"
+		:param what: what other than then position to export. parameter is list of couple (name,command). Name is string under which it is save to vtk, command is string to evaluate. Note that the bodies are labeled as b in this function. Scalar, vector and tensor variables are supported. For example, to export velocity (with name particleVelocity) and the distance form point (0,0,0) (named as dist) you should write: ... what=[('particleVelocity','b.state.vel'),('dist','b.state.pos.norm()', ...
+		:type what: [tuple(2)]
+		:param string comment: comment to add to vtk file
+		:param int numLabel: number of file (e.g. time step), if unspecified, the last used value + 1 will be used
+		"""
+		# TODO useRef?
+		allIds = False
+		if ids=='all':
+			ids=xrange(len(O.bodies))
+			allIds = True
+		bodies = []
+		for i in ids:
+			b = O.bodies[i]
+			if not b: continue
+			if b.shape.__class__.__name__!="Polyhedra":
+				if not allIds: print "Warning: body %d is not Polyhedra"%(i)
+				continue
+			bodies.append(b)
+		n = len(bodies)
+		nVertices = sum(len(b.shape.v) for b in bodies)
+		bodyFaces = []
+		for b in bodies:
+			ff = []
+			f = b.shape.GetSurfaceTriangulation()
+			for i in xrange(len(f)/3):
+				ff.append([f[3*i+j] for j in (0,1,2)])
+			bodyFaces.append(ff)
+		nFaces = sum(len(f) for f in bodyFaces)
+		fName = self.baseName+'-polyhedra-%04d'%(numLabel if numLabel else self.polyhedraSnapCount)+'.vtk'
+		outFile = open(fName, 'w')
+		outFile.write("# vtk DataFile Version 3.0.\n%s\nASCII\n\nDATASET POLYDATA\nPOINTS %d double\n"%(comment,nVertices))
+		for b in bodies:
+			bPos = b.state.pos
+			bOri = b.state.ori
+			for v in b.shape.v:
+				pos = bPos + bOri*v
+				outFile.write("%g %g %g\n"%(pos[0],pos[1],pos[2]))
+		outFile.write("\nPOLYGONS %d %d\n"%(nFaces,4*nFaces))
+		j = 0
+		for i,b in enumerate(bodies):
+			faces = bodyFaces[i]
+			for face in faces:
+				t = tuple([j+ii for ii in face])
+				outFile.write("3 %d %d %d\n"%t)
+			j += len(b.shape.v)
+		if what:
+			outFile.write("\nCELL_DATA %d"%(nFaces))
+		for name,command in what:
+			test = eval(command)
+			if isinstance(test,Matrix3):
+				outFile.write("\nTENSORS %s double\n"%(name))
+				for i,b in enumerate(bodies):
+					t = eval(command)
+					for f in bodyFaces[i]:
+						outFile.write("%g %g %g\n%g %g %g\n%g %g %g\n\n"%(t[0,0],t[0,1],t[0,2],t[1,0],t[1,1],t[1,2],t[2,0],t[2,1],t[2,2]))
+			elif isinstance(test,Vector3):
+				outFile.write("\nVECTORS %s double\n"%(name))
+				for i,b in enumerate(bodies):
+					v = eval(command)
+					for f in bodyFaces[i]:
+						outFile.write("%g %g %g\n"%(v[0],v[1],v[2]))
+			elif isinstance(test,(int,float)):
+				outFile.write("\nSCALARS %s double 1\nLOOKUP_TABLE default\n"%(name))
+				for i,b in enumerate(bodies):
+					e = eval(command)
+					for f in bodyFaces[i]:
+						outFile.write("%g\n"%e)
+			else:
+				print 'WARNING: export.VTKExporter.exportPolyhedra: wrong `what` parameter, vtk output might be corrupted'
+		outFile.close()
+		self.polyhedraSnapCount += 1
+
+	
 
 
 #gmshGeoExport===============================================================
@@ -666,3 +834,103 @@
 			pass
 	out.close()
 	return count
+
+
+
+
+# external vtk manipulation ===============================================================
+def text2vtk(inFileName,outFileName):
+	"""Converts text file (created by :yref:`yade.export.textExt` function) into vtk file.
+	See :ysrc:`examples/test/paraview-spheres-solid-section/export_text.py` example
+
+	:param str inFileName: name of input text file
+	:param str outFileName: name of output vtk file
+	"""
+	fin  = open(inFileName)
+	fout = open(outFileName,'w')
+	lastLine = None
+	line = '#'
+	while line.startswith('#'):
+		lastLine = line
+		line = fin.readline()
+	columns = lastLine.split()[5:]
+	data = [line.split() for line in fin]
+	fin.close()
+	n = len(data)
+	fout.write('# vtk DataFile Version 3.0.\ncomment\nASCII\n\nDATASET POLYDATA\nPOINTS %d double\n'%(n))
+	fout.writelines('%s %s %s\n'%(d[0],d[1],d[2]) for d in data)
+	fout.write("\nPOINT_DATA %d\nSCALARS radius double 1\nLOOKUP_TABLE default\n"%(n))
+	fout.writelines('%s\n'%(d[3]) for d in data)
+	for i,c in enumerate(columns):
+		fout.write("\nSCALARS %s double 1\nLOOKUP_TABLE default\n"%(c))
+		fout.writelines('%s\n'%(d[4+i]) for d in data)
+	fout.close()
+
+def text2vtkSection(inFileName,outFileName,point,normal=(1,0,0)):
+	"""Converts section through spheres from text file (created by :yref:`yade.export.textExt` function) into vtk file.
+	See :ysrc:`examples/test/paraview-spheres-solid-section/export_text.py` example
+
+	:param str inFileName: name of input text file
+	:param str outFileName: name of output vtk file
+	:param Vector3|(float,float,float) point: coordinates of a point lying on the section plane
+	:param Vector3|(float,float,float) normal: normal vector of the section plane
+	"""
+	from math import sqrt
+	norm = sqrt(pow(normal[0],2)+pow(normal[1],2)+pow(normal[2],2))
+	normal = (normal[0]/norm,normal[1]/norm,normal[2]/norm)
+	#
+	def computeD(point,normal):
+		# from point and normal computes parameter d in plane equation ax+by+cz+d=0
+		return -normal[0]*point[0] - normal[1]*point[1] - normal[2]*point[2]
+	def computeDistanceFromPlane(dat,point,normal,d=None):
+		# computes distance of sphere dat from plane (point,normal)
+		x,y,z = computeProjectionOnPlane(dat,point,normal,d)
+		cx,cy,cz = dat[0],dat[1],dat[2]
+		return sqrt(pow(x-cx,2)+pow(y-cy,2)+pow(z-cz,2))
+	def computeProjectionOnPlane(self,point,normal,d=None):
+		# computes projection of sphere dat on plane (point,normal)
+		if d is None:
+			d = computeD(point,normal)
+		nx,ny,nz = normal[0],normal[1],normal[2]
+		cx,cy,cz = dat[0],dat[1],dat[2]
+		t = (-d-nx*cx-ny*cy-nz*cz) / (nx*nx+ny*ny+nz*nz)
+		x,y,z = cx+t*nx, cy+t*ny, cz+t*nz
+		return x,y,z
+	#
+	fin  = open(inFileName)
+	lastLine = None
+	line = '#'
+	while line.startswith('#'):
+		lastLine = line
+		line = fin.readline()
+	columns = lastLine.split()[4:]
+	data = [[float(w) for w in line.split()] for line in fin]
+	fin.close()
+	#
+	d = computeD(point,normal)
+	circs = []
+	for dat in data:
+		r = dat[3]
+		dst = computeDistanceFromPlane(dat,point,normal,d)
+		if dst > r:
+			continue
+		x,y,z = computeProjectionOnPlane(dat,point,normal,d)
+		rNew = sqrt(r*r-dst*dst)
+		dNew = [x,y,z,rNew,r]
+		dNew.extend(dat[4:])
+		circs.append(dNew)
+	n = len(circs)
+	fout = open(outFileName,'w')
+	fout.write('# vtk DataFile Version 3.0.\ncomment\nASCII\n\nDATASET POLYDATA\nPOINTS %d double\n'%(n))
+	fout.writelines('%g %g %g\n'%(c[0],c[1],c[2]) for c in circs)
+	fout.write("\nPOINT_DATA %d\nSCALARS radius double 1\nLOOKUP_TABLE default\n"%(n))
+	fout.writelines('%g\n'%(c[3]) for c in circs)
+	fout.write("\nSCALARS radiusOrig double 1\nLOOKUP_TABLE default\n")
+	fout.writelines('%g\n'%(c[4]) for c in circs)
+	fout.write("\nVECTORS normal double\n")
+	fout.writelines("%g %g %g\n"%normal for i in circs)
+	for i,c in enumerate(columns):
+		fout.write("\nSCALARS %s double 1\nLOOKUP_TABLE default\n"%(c))
+		fout.writelines('%s\n'%(c[4+i]) for c in circs)
+	fout.close()
+

=== modified file 'py/geom.py'
--- py/geom.py	2013-03-08 21:26:47 +0000
+++ py/geom.py	2014-01-14 18:37:09 +0000
@@ -90,7 +90,10 @@
 	return ret
 
 #facetCylinder==========================================================
-def facetCylinder(center,radius,height,orientation=Quaternion.Identity,segmentsNumber=10,wallMask=7,angleRange=None,closeGap=False,**kw):
+def facetCylinder(center,radius,height,orientation=Quaternion.Identity,
+	segmentsNumber=10,wallMask=7,angleRange=None,closeGap=False,
+	radiusTopInner=-1, radiusBottomInner=-1,
+	**kw):
 	"""
 	Create arbitrarily-aligned cylinder composed of facets, with given center, radius, height and orientation.
 	Return List of facets forming the cylinder;
@@ -98,6 +101,8 @@
 	:param Vector3 center: center of the created cylinder
 	:param float radius:  cylinder radius
 	:param float height: cylinder height
+	:param float radiusTopInner: inner radius of cylinders top, -1 by default
+	:param float radiusBottomInner: inner radius of cylinders bottom, -1 by default
 	:param Quaternion orientation: orientation of the cylinder; the reference orientation has axis along the $+x$ axis.
 	:param int segmentsNumber: number of edges on the cylinder surface (>=5)
 	:param bitmask wallMask: determines which walls will be created, in the order up (1), down (2), side (4). The numbers are ANDed; the default 7 means to create all walls
@@ -109,7 +114,11 @@
 	if (radius<=0): raise RuntimeError("The radius should have the positive value");
 	if (height<=0): wallMask = 1;
 	
-	return facetCylinderConeGenerator(center=center,radiusTop=radius,height=height,orientation=orientation,segmentsNumber=segmentsNumber,wallMask=wallMask,angleRange=angleRange,closeGap=closeGap,**kw)
+	return facetCylinderConeGenerator(center=center,radiusTop=radius,height=height,
+		orientation=orientation,segmentsNumber=segmentsNumber,wallMask=wallMask,
+		angleRange=angleRange,closeGap=closeGap,
+		radiusTopInner=radiusTopInner, radiusBottomInner=radiusBottomInner,
+		**kw)
 
 #facetSphere==========================================================
 def facetSphere(center,radius,thetaResolution=8,phiResolution=8,returnElementMap=False,**kw):
@@ -155,7 +164,10 @@
 
 
 #facetCone==============================================================
-def facetCone(center,radiusTop,radiusBottom,height,orientation=Quaternion.Identity,segmentsNumber=10,wallMask=7,angleRange=None,closeGap=False,**kw):
+def facetCone(center,radiusTop,radiusBottom,height,orientation=Quaternion.Identity,
+	segmentsNumber=10,wallMask=7,angleRange=None,closeGap=False,
+	radiusTopInner=-1, radiusBottomInner=-1,
+	**kw):
 	"""
 	Create arbitrarily-aligned cone composed of facets, with given center, radius, height and orientation.
 	Return List of facets forming the cone;
@@ -163,6 +175,8 @@
 	:param Vector3 center: center of the created cylinder
 	:param float radiusTop:  cone top radius
 	:param float radiusBottom:  cone bottom radius
+	:param float radiusTopInner: inner radius of cones top, -1 by default
+	:param float radiusBottomInner: inner radius of cones bottom, -1 by default
 	:param float height: cone height
 	:param Quaternion orientation: orientation of the cone; the reference orientation has axis along the $+x$ axis.
 	:param int segmentsNumber: number of edges on the cone surface (>=5)
@@ -174,7 +188,11 @@
 	# check zero dimentions
 	if ((radiusBottom<=0) and (radiusTop<=0)): raise RuntimeError("The radiusBottom or radiusTop should have the positive value");
 	
-	return facetCylinderConeGenerator(center=center,radiusTop=radiusTop,radiusBottom=radiusBottom,height=height,orientation=orientation,segmentsNumber=segmentsNumber,wallMask=wallMask,angleRange=angleRange,closeGap=closeGap,**kw)
+	return facetCylinderConeGenerator(center=center,radiusTop=radiusTop,
+		radiusBottom=radiusBottom,height=height,orientation=orientation,segmentsNumber=segmentsNumber,
+		wallMask=wallMask,angleRange=angleRange,closeGap=closeGap,
+		radiusTopInner=radiusTopInner, radiusBottomInner=radiusBottomInner,
+		**kw)
 
 #facetPolygon===========================================================
 def facetPolygon(center,radiusOuter,orientation=Quaternion.Identity,segmentsNumber=10,angleRange=None,radiusInner=0,**kw):
@@ -324,7 +342,12 @@
 
 
 #facetCylinderConeGenerator=============================================
-def facetCylinderConeGenerator(center,radiusTop,height,orientation=Quaternion.Identity,segmentsNumber=10,wallMask=7,angleRange=None,closeGap=False,radiusBottom=-1,**kw):
+def facetCylinderConeGenerator(center,radiusTop,height,orientation=Quaternion.Identity,
+	segmentsNumber=10,wallMask=7,angleRange=None,closeGap=False,
+	radiusBottom=-1,
+	radiusTopInner=-1,
+	radiusBottomInner=-1,
+	**kw):
 	"""
 	Please, do not use this function directly! Use geom.facetCylinder and geom.facetCone instead.
 	This is the base function for generating cylinders and cones from facets.
@@ -336,6 +359,9 @@
 	#For cylinders top and bottom radii are equal
 	if (radiusBottom == -1):
 		radiusBottom = radiusTop
+	
+	if ((radiusTopInner > 0 and radiusTopInner > radiusTop) or (radiusBottomInner > 0 and radiusBottomInner > radiusBottom)): 
+		raise RuntimeError("The internal radius cannot be larger than outer");
 	# check zero dimentions
 	if (segmentsNumber<3): raise RuntimeError("The segmentsNumber should be at least 3");
 	if (height<0): raise RuntimeError("The height should have the positive value");
@@ -350,26 +376,47 @@
 	anglesInRad = numpy.linspace(angleRange[0], angleRange[1], segmentsNumber+1, endpoint=True)
 	
 	PTop=[]; PTop.append(Vector3(0,0,+height/2))
+	PTopIn=[]; PTopIn.append(Vector3(0,0,+height/2))
+	
 	PBottom=[]; PBottom.append(Vector3(0,0,-height/2))
-
+	PBottomIn=[]; PBottomIn.append(Vector3(0,0,-height/2))
+	
 	for i in anglesInRad:
 		XTop=radiusTop*math.cos(i); YTop=radiusTop*math.sin(i); 
 		PTop.append(Vector3(XTop,YTop,+height/2))
+		if (radiusTopInner > 0):
+			XTopIn=radiusTopInner*math.cos(i); YTopIn=radiusTopInner*math.sin(i); 
+			PTopIn.append(Vector3(XTopIn,YTopIn,+height/2))
 		
 		XBottom=radiusBottom*math.cos(i); YBottom=radiusBottom*math.sin(i); 
 		PBottom.append(Vector3(XBottom,YBottom,-height/2))
+		if (radiusBottomInner > 0):
+			XBottomIn=radiusBottomInner*math.cos(i); YBottomIn=radiusBottomInner*math.sin(i);
+			PBottomIn.append(Vector3(XBottomIn,YBottomIn,-height/2))
 		
 	for i in range(0,len(PTop)):
 		PTop[i]=orientation*PTop[i]+center
 		PBottom[i]=orientation*PBottom[i]+center
+		if (len(PTopIn)>1):
+			PTopIn[i]=orientation*PTopIn[i]+center
+		if (len(PBottomIn)>1):
+			PBottomIn[i]=orientation*PBottomIn[i]+center
 
 	ret=[]
 	for i in range(2,len(PTop)):
 		if (wallMask&1)and(radiusTop!=0):
-			ret.append(utils.facet((PTop[0],PTop[i],PTop[i-1]),**kw))
+			if (len(PTopIn)>1):
+				ret.append(utils.facet((PTop[i-1],PTopIn[i],PTopIn[i-1]),**kw))
+				ret.append(utils.facet((PTop[i-1],PTop[i],PTopIn[i]),**kw))
+			else:
+				ret.append(utils.facet((PTop[0],PTop[i],PTop[i-1]),**kw))
 			
 		if (wallMask&2)and(radiusBottom!=0):
-			ret.append(utils.facet((PBottom[0],PBottom[i-1],PBottom[i]),**kw))
+			if (len(PBottomIn)>1):
+				ret.append(utils.facet((PBottom[i-1],PBottomIn[i],PBottomIn[i-1]),**kw))
+				ret.append(utils.facet((PBottom[i-1],PBottom[i],PBottomIn[i]),**kw))
+			else:
+				ret.append(utils.facet((PBottom[0],PBottom[i-1],PBottom[i]),**kw))
 			
 		if wallMask&4:
 			if (radiusBottom!=0):

=== modified file 'py/pack/pack.py'
--- py/pack/pack.py	2013-09-19 08:50:04 +0000
+++ py/pack/pack.py	2014-01-06 14:10:07 +0000
@@ -264,6 +264,8 @@
 	xx,yy,zz=[arange(mn[i]+radius,mx[i]-radius,2*radius+gap) for i in 0,1,2]
 	for xyz in itertools.product(xx,yy,zz):
 		if predicate(xyz,radius): ret+=[utils.sphere(xyz,radius=radius,**kw)]
+	if (len(ret)==0):
+		warnings.warn('No spheres are produced by regularOrtho-function',category=RuntimeWarning)
 	return ret
 
 def regularHexa(predicate,radius,gap,**kw):
@@ -283,6 +285,8 @@
 		if j%2==0: x+= a/2. if k%2==0 else -a/2.
 		if k%2!=0: x+=a/2.; y+=hy/2.
 		if predicate((x,y,z),radius): ret+=[utils.sphere((x,y,z),radius=radius,**kw)]
+	if (len(ret)==0):
+		warnings.warn('No spheres are produced by regularHexa-function',category=RuntimeWarning)
 	return ret
 
 def filterSpherePack(predicate,spherePack,returnSpherePack=None,**kw):
@@ -459,7 +463,7 @@
 		# repetition to the required cell size will be done below, after memoizing the result
 	else:
 		assumedFinalDensity=0.6
-		V=(4/3)*pi*radius**3; N=assumedFinalDensity*fullDim[0]*fullDim[1]*fullDim[2]/V;
+		V=(4.0/3.0)*pi*radius**3.0; N=assumedFinalDensity*fullDim[0]*fullDim[1]*fullDim[2]/V;
 		TriaxialTest(
 			numberOfGrains=int(N),radiusMean=radius,radiusStdDev=rRelFuzz,
 			# upperCorner is just size ratio, if radiusMean is specified

=== modified file 'py/runtime.py'
--- py/runtime.py	2012-07-09 18:23:32 +0000
+++ py/runtime.py	2014-01-14 18:37:09 +0000
@@ -7,7 +7,7 @@
 # find out about which ipython version we use -- 0.10* and 0.11 are supported, but they have different internals
 import IPython
 try: # attempt to get numerical version
-	ipython_version=int(IPython.__version__.split('.',2)[1]) ## convert '0.10' to 10, '0.11.alpha1.bzr.r1223' to 11
+	ipython_version=int(IPython.__version__.split('.')[0])*100 + int(IPython.__version__.split('.')[1])
 except ValueError:
 	print 'WARN: unable to extract IPython version from %s, defaulting to 10'%(IPython.__version__)
 	ipython_version=10

=== modified file 'py/tests/cohesive-chain.py'
--- py/tests/cohesive-chain.py	2013-03-08 21:26:47 +0000
+++ py/tests/cohesive-chain.py	2014-01-23 18:08:34 +0000
@@ -10,7 +10,6 @@
 from yade.wrapper import *
 from yade._customConverters import *
 from yade import utils
-from yade import *
 from math import *
 
 try:

=== modified file 'py/utils.py'
--- py/utils.py	2013-10-15 17:11:37 +0000
+++ py/utils.py	2014-02-12 13:18:59 +0000
@@ -254,7 +254,7 @@
 	_commonBodySetup(b,V,Vector3(geomInert,geomInert,geomInert),material,pos=begin,resetState=False,dynamic=dynamic,fixed=fixed)
 	b.mask=mask
 	b.bound=Aabb(color=[0,1,0])
-	b.state.ori=b.state.ori.setFromTwoVectors(Vector3(0.,0.,1.),segment)
+	b.state.ori.setFromTwoVectors(Vector3(0.,0.,1.),segment)
 	if (end == begin): b.state.ori = Quaternion((1,0,0),0)
 	return b
 
@@ -303,7 +303,7 @@
 	I=math.pi*(2.*radius)**4/64.
 	E=nodeMat.young
 	i.phys.kn=E*math.pi*(radius**2)/L
-	i.phys.kr=2.*E*I/L
+	i.phys.kr=E*I/L
 	i.phys.ks=12.*E*I/(L**3)
 	G=E/(2.*(1+nodeMat.poisson))
 	i.phys.ktw=2.*I*G/L

=== modified file 'py/ymport.py'
--- py/ymport.py	2013-08-14 08:59:42 +0000
+++ py/ymport.py	2014-01-16 09:59:51 +0000
@@ -11,7 +11,7 @@
 	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.
+	"""Load sphere coordinates from file in specific format, returns a list of corresponding bodies; that may be inserted to the simulation with O.bodies.append().
 	
 	:param str filename: file name
 	:param str format: the name of output format. Supported `x_y_z_r`(default), `x_y_z_r_matId`
@@ -47,9 +47,49 @@
 		else:
 			raise RuntimeError("Please, specify a correct format output!");
 	return ret
+  
+def textClumps(fileName,shift=Vector3.Zero,scale=1.0,**kw):
+	"""Load clumps-members from file, insert them to the simulation.
+	
+	:param str filename: file name
+	:param str format: the name of output format. Supported `x_y_z_r`(default), `x_y_z_r_matId`
+	:param [float,float,float] 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.sphere`
+	:returns: list of spheres.
+
+	Lines starting with # are skipped
+	"""
+	infile = open(fileName,"r")
+	lines = infile.readlines()
+	infile.close()
+	ret=[]
+	
+	curClump=[]
+	newClumpId = -1
+	
+	for line in lines:
+		data = line.split()
+		if (data[0][0] == "#"): continue
+		pos = Vector3(float(data[0]),float(data[1]),float(data[2]))
+	
+		if (newClumpId<0 or newClumpId==int(data[4])):
+			idD = curClump.append(utils.sphere(shift+scale*pos,scale*float(data[3]),**kw))
+			newClumpId = int(data[4])
+			ret.append(idD)
+		else:
+			newClumpId = int(data[4])
+			O.bodies.appendClumped(curClump)
+			curClump=[]
+			idD = curClump.append(utils.sphere(shift+scale*pos,scale*float(data[3]),**kw))
+			ret.append(idD)
+	
+	if (len(curClump)<>0):
+		O.bodies.appendClumped(curClump)
+	return ret
 
 def text(fileName,shift=Vector3.Zero,scale=1.0,**kw):
-	"""Load sphere coordinates from file, create spheres, insert them to the simulation.
+	"""Load sphere coordinates from file, returns a list of corresponding bodies; that may be inserted to the simulation with O.bodies.append().
 
 	:param string filename: file which has 4 colums [x, y, z, radius].
 	:param [float,float,float] shift: [X,Y,Z] parameter moves the specimen.

=== modified file 'scripts/checks-and-tests/checks/DEM-PFV-check.py'
--- scripts/checks-and-tests/checks/DEM-PFV-check.py	2013-08-30 10:33:17 +0000
+++ scripts/checks-and-tests/checks/DEM-PFV-check.py	2014-01-23 18:10:35 +0000
@@ -23,7 +23,8 @@
 	wallIds=O.bodies.append(walls)
 
 	sp=pack.SpherePack()
-	#sp.makeCloud(mn,mx,-1,0.3333,num_spheres,False, 0.95,seed=1) #"seed" is not enough for portable determinism it seems, let us use a data file
+	sp.makeCloud(mn,mx,-1,0.3333,num_spheres,False, 0.95,seed=0) #"seed" is not enough for portable determinism it seems, let us use a data file
+	checksPath="/home/3S-LAB/bchareyre/yade/yade-git/trunk/scripts/checks-and-tests/checks"
 	sp.load(checksPath+'/data/100spheres')
 
 	sp.toSimulation(material='spheres')
@@ -79,7 +80,7 @@
 	e22=e22-triax.strain[1]
 	modulus = 1000./abs(e22)
 
-	target=249064.586653
+	target=252759.905803
 	if abs((modulus-target)/target)>tolerance :
 		print "DEM-PFV: difference in bulk modulus:", modulus, "vs. target ",target
 		errors+=1
@@ -101,11 +102,11 @@
 	Qout = flow.getBoundaryFlux(3)
 	permeability = abs(Qin)/1.e-4 #size is one, we compute K=V/∇H
 
-	if abs(Qin+Qout)>1e-15 :
-		print "DEM-PFV: unbalanced Qin vs. Qout"
+	if abs(Qin+Qout)>1e-10 :
+		print "DEM-PFV: unbalanced Qin vs. Qout (",Qin," vs. ",Qout,")"
 		errors+=1
 
-	target=0.0408678245942
+	target=0.040399916554
 	if abs((permeability-target)/target)>tolerance :
 		print "DEM-PFV: difference in permeability:",permeability," vs. target ",target
 		errors+=1
@@ -123,18 +124,17 @@
 	from yade import timing
 	O.run(3000,1)
 
-	target=637.268936033
+	target=628.314160434
 	if abs((flow.getPorePressure((0.5,0.1,0.5))-target)/target)>tolerance :
 		print "DEM-PFV: difference in final pressure:",flow.getPorePressure((0.5,0.1,0.5))," vs. target ",target
 		errors+=1
-	target=0.00260892345196
+	target=0.00258113045083
 	if abs((triax.strain[1]-zeroe22-target)/target)>tolerance :
 		print "DEM-PFV: difference in final deformation",triax.strain[1]-zeroe22," vs. target ",target
 		errors+=1
 
 	if (float(flow.execTime)/float(sum([e.execTime for e in O.engines])))>0.6 :
-		print "DEM-PFV: More than 60\% of cpu time in FlowEngine (",100.*(float(flow.execTime)/float(sum([e.execTime for e in O.engines]))) ,"%). Should not happen with efficient libraries (check blas/lapack/cholmod implementations)"
-		errors+=1
+		print "(INFO) DEM-PFV: More than 60\% of cpu time in FlowEngine (",100.*(float(flow.execTime)/float(sum([e.execTime for e in O.engines]))) ,"%). Should not happen with efficient libraries (check blas/lapack/cholmod implementations)"
 
 	flow.forceMetis=True
 	O.run(201,1)

=== added file 'scripts/checks-and-tests/checks/checkViscElEng.py'
--- scripts/checks-and-tests/checks/checkViscElEng.py	1970-01-01 00:00:00 +0000
+++ scripts/checks-and-tests/checks/checkViscElEng.py	2013-12-04 15:43:55 +0000
@@ -0,0 +1,59 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+# 2 spheres. One is fixed, another one failing from up.
+# Calculate en (coefficient of restitution) and compare with precalculated value
+# Coefficient of restitution is the ratio of speeds after and before an impact
+# This check-simulation checks the correctness of ViscoElasticEngine
+
+from yade import utils, plot
+o = Omega()
+fr = 0.5;rho=2000
+tc = 0.001; en = 0.7; et = 0.7; o.dt = 0.0002*tc
+
+
+r1 = 0.003
+r2 = 0.002
+
+
+param = getViscoelasticFromSpheresInteraction(tc,en,et)
+
+mat1 = O.materials.append(ViscElMat(frictionAngle=fr,density=rho,**param))
+
+
+id1 = O.bodies.append(sphere(center=[0,0,0],radius=r1,material=mat1,fixed=True))
+id2 = O.bodies.append(sphere(center=[0,0,(r1+r2*2.0)],radius=r2,material=mat1,fixed=False))
+
+
+o.engines = [
+  ForceResetter(),
+  InsertionSortCollider([Bo1_Sphere_Aabb()],verletDist=(r1+r2)*5.0),
+  InteractionLoop(
+    [Ig2_Sphere_Sphere_ScGeom()],
+    [Ip2_ViscElMat_ViscElMat_ViscElPhys()],
+    [Law2_ScGeom_ViscElPhys_Basic()],
+  ),
+  NewtonIntegrator(damping=0,gravity=[0,0,-9.81]),
+  PyRunner(command='addPlotData()',iterPeriod=100),
+]
+
+v0 = 0
+en = 0
+tolerance = 0.0001
+
+def addPlotData(): 
+  global v0, en
+  v = O.bodies[id2].state.vel[2]
+
+  if v0<=0 and v>0:
+    en=-v/v0
+    print ("Precalculated en value %f" % 0.736356797441)
+    print ("Obtained en value %f" % en)
+    O.pause()
+  v0=v
+
+O.run(1000000)
+O.wait()
+
+if ((abs(0.736356797441-en)/en)>tolerance):
+  resultStatus += 1

=== modified file 'scripts/checks-and-tests/checks/checkWeight.py'
--- scripts/checks-and-tests/checks/checkWeight.py	2012-04-13 16:27:00 +0000
+++ scripts/checks-and-tests/checks/checkWeight.py	2014-01-20 08:45:23 +0000
@@ -43,7 +43,7 @@
 ]
 
 
-O.run(10000)
+O.run(30000)
 O.wait()
 curForce = utils.sumForces(ids=floorId,direction=Vector3(0,0,1))*(-1)
 print ("Precalculated weight %f" % sphMass)

=== added file 'scripts/ppa/.dput.cf'
--- scripts/ppa/.dput.cf	1970-01-01 00:00:00 +0000
+++ scripts/ppa/.dput.cf	2013-12-20 15:10:54 +0000
@@ -0,0 +1,6 @@
+[mini]
+fqdn = localhost
+method = local
+incoming = /home/USER/M/Temp/archive/mini-dinstall/incoming
+allow_unsigned_uploads = 1
+post_upload_command = mini-dinstall --batch

=== added file 'scripts/ppa/.mini-dinstall.conf'
--- scripts/ppa/.mini-dinstall.conf	1970-01-01 00:00:00 +0000
+++ scripts/ppa/.mini-dinstall.conf	2014-02-04 15:21:18 +0000
@@ -0,0 +1,22 @@
+[DEFAULT]
+architectures = all, i386, amd64
+incoming_permissions = 0750
+archivedir = /home/USER/M/Temp/archive/
+mail_on_success = 0
+dynamic_reindex = 1
+archive_style = flat
+generate_release = 1
+keep_old = 0
+release_description = YADE Debian/Ubuntu daily packages
+
+[wheezy]
+
+[jessie]
+
+[unstable]
+
+[precise]
+
+[saucy]
+
+[trusty]

=== added file 'scripts/ppa/buildppa.py'
--- scripts/ppa/buildppa.py	1970-01-01 00:00:00 +0000
+++ scripts/ppa/buildppa.py	2014-01-10 20:03:14 +0000
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+import argparse, os, git, shutil, sys, time
+
+
+parser = argparse.ArgumentParser(description='Process some integers.')
+parser.add_argument("-i", help="config file")
+parser.add_argument("-u","--update", help="update tarballs, if they are exist", action='store_true')
+parser.add_argument("-j", help="number of processors to build",dest='jobsNumber',default=6, type=int)
+args = parser.parse_args() 
+
+
+configfile = args.i
+jobsNumber = args.jobsNumber
+
+infileconf  = open(configfile)
+linesconf   = infileconf.readlines()
+gitdebdir   = linesconf[1].strip()
+pbdir       = linesconf[4].strip()
+gitupsdir   = linesconf[7].strip()
+userg       = linesconf[10].strip()
+groupg      = linesconf[13].strip()
+dputg       = linesconf[16].strip()
+keyg        = linesconf[19].strip()
+keypasspath = linesconf[22].strip()
+keysecrpath = linesconf[25].strip()
+patharchive = linesconf[28].strip()
+
+if not(os.path.isdir(gitdebdir)):
+    raise RuntimeError('Git-debian-directory does not exists')
+
+if not(os.path.isdir(gitupsdir)):
+    raise RuntimeError('Git-upstream-directory does not exists')
+
+if not(os.path.isdir(pbdir)):
+    print ('Pbuilder-directory does not exists. Creating')
+    os.mkdir(pbdir)
+
+repodeb = git.Repo(gitdebdir)
+repoups = git.Repo(gitupsdir)
+assert repodeb.bare == False
+assert repoups.bare == False
+
+if (repodeb.is_dirty()):
+    raise RuntimeError('Git-debian-repo has an uncommitted changes. Exiting.')
+
+if (repoups.is_dirty()):
+    raise RuntimeError('Git-upstream-repo has an uncommitted changes. Exiting.')
+
+for branch in repodeb.branches:
+    branchstr = str(branch)
+    if (branchstr<>'master'):
+        print "Switching to branch %s"%(branch)
+        repodeb.git.checkout(branch)
+        infile = open(gitdebdir+"/pbuilder")
+        lines = infile.readlines()
+        mirror = lines[0].strip()
+        components = lines[1].strip()
+        archs = lines[2].split()
+        keyringuse = lines[3].strip()
+        othermirror = lines[4].strip()
+        infile.close()
+        for a in archs:
+            tarball = "%s/%s_%s.tgz"%(pbdir, branchstr, a.strip())
+            addAllowuntrusted = ""
+            if (othermirror!="#"):
+                addAllowuntrusted =  " --allow-untrusted "
+            if not(os.path.isfile(tarball)):
+                createPbTar = ('sudo pbuilder --create --distribution %s --mirror %s --components "%s" --architecture %s --debootstrapopts "--keyring=%s" --basetgz %s'%
+                        (branchstr, mirror, components, a, keyringuse, tarball))
+                if (othermirror!="#"):
+                    createPbTar += ' --othermirror "' + othermirror + '"'
+                    addAllowuntrusted =  " --allow-untrusted "
+                print createPbTar
+
+                print "Creating tarball %s"%(tarball)
+                os.system(createPbTar)
+            else:
+                print "Tarball %s exists"%(tarball)
+                if (args.update):
+                    print "Updating %s as requested" %(tarball)
+                    updatePbTar = ('sudo pbuilder --update --basetgz %s'%(tarball))
+                    os.system(updatePbTar)
+            
+            # Creating dir for building
+
+            builddirup="%s_%s/"%(branchstr, a)
+            builddirdeb="%s/build/"%(builddirup)
+            builddirres="%s/result/"%(builddirup)
+            #shutil.rmtree(builddirdeb,ignore_errors=True)
+            shutil.rmtree(builddirup,ignore_errors=True)
+            shutil.copytree(gitupsdir, builddirdeb )
+            shutil.rmtree(builddirdeb+".git")
+            # Get package version
+            versiondebian = repoups.git.describe()[0:-8] + repoups.head.commit.hexsha[0:7] + "~" + branchstr
+
+            # Get package name
+            infilepname = open(gitdebdir+"/changelog"); sourcePackName = infilepname.readlines()[0].split()[0]
+            print sourcePackName
+
+            os.system('cd %s; apack %s_%s.orig.tar.xz build'%(builddirup,sourcePackName,versiondebian))
+            shutil.copytree(gitdebdir, builddirdeb+"/debian")
+
+            os.system('sed -i.bak -e s/VERSION/%s/ -e s/DISTRIBUTION/%s/ %s/debian/changelog'%(versiondebian,branch,builddirdeb))
+            os.system('sed -i.bak -e s/VERSIONYADEREPLACE/%s/ %s/debian/rules'%(versiondebian,builddirdeb))
+            os.system('cd %s; dpkg-source -b -I build'%(builddirup))
+            os.mkdir(builddirres)
+            print "Building package %s_%s"%(sourcePackName, versiondebian)
+            buildPackage = ('sudo pbuilder --build --architecture %s --basetgz %s %s --logfile %s/pbuilder.log --debbuildopts "-j%d" --buildresult %s %s/*.dsc'%
+                (a, tarball, addAllowuntrusted, builddirup, jobsNumber, builddirres, builddirup))
+            print buildPackage
+            os.system(buildPackage)
+            os.system('sudo chown %s:%s %s * -R'%(userg, groupg, builddirup))
+            os.system('sudo chown %s:%s %s * -R'%(userg, groupg, gitdebdir))
+            os.system('sudo chown %s:%s %s * -R'%(userg, groupg, gitupsdir))
+        os.system('cd %s ; su %s -c \'dput %s *.changes\''%(builddirres, userg, dputg))
+
+for branch in repodeb.branches:
+    branchstr = str(branch)
+    if (branchstr<>'master'):
+        os.system('rm %s/%s/Release.gpg ; su %s -c \'gpg --no-tty --batch --default-key "%s" --detach-sign --passphrase-fd=0 --passphrase-file=%s -o %s/%s/Release.gpg %s/%s/Release\''%(patharchive, branch, userg, keyg, keypasspath, patharchive, branch, patharchive, branch))

=== removed file 'scripts/ppa/createtar.py'
--- scripts/ppa/createtar.py	2013-11-18 20:26:55 +0000
+++ scripts/ppa/createtar.py	1970-01-01 00:00:00 +0000
@@ -1,91 +0,0 @@
-#!/usr/bin/env python
-import argparse, os, git, shutil
-
-jobsNumber = 4
-
-parser = argparse.ArgumentParser(description='Process some integers.')
-parser.add_argument("g", help="git debian-directory")
-parser.add_argument("p", help="direcrory, where will be created pbuilder tarballs")
-parser.add_argument("u", help="git upstream-direcrory")
-parser.add_argument("-u","--update", help="update tarballs, if they are exist", action='store_true')
-args = parser.parse_args() 
-
-gitdebdir = args.g
-gitupsdir = args.u
-pbdir     = args.p
-
-if not(os.path.isdir(gitdebdir)):
-    raise RuntimeError('Git-debian-directory does not exists')
-
-if not(os.path.isdir(gitupsdir)):
-    raise RuntimeError('Git-upstream-directory does not exists')
-
-if not(os.path.isdir(pbdir)):
-    print ('Pbuilder-directory does not exists. Creating')
-    os.mkdir(pbdir)
-
-repodeb = git.Repo(gitdebdir)
-repoups = git.Repo(gitupsdir)
-assert repodeb.bare == False
-assert repoups.bare == False
-
-if (repodeb.is_dirty()):
-    raise RuntimeError('Git-debian-repo has an uncommitted changes. Exiting.')
-
-if (repoups.is_dirty()):
-    raise RuntimeError('Git-upstream-repo has an uncommitted changes. Exiting.')
-
-for branch in repodeb.branches:
-    branchstr = str(branch)
-    if (branchstr<>'master'):
-        print "Switching to branch %s"%(branch)
-        repodeb.git.checkout(branch)
-        infile = open(gitdebdir+"/pbuilder")
-        lines = infile.readlines()
-        mirror = lines[0].strip()
-        components = lines[1].strip()
-        archs = lines[2].split()
-        keyringuse = lines[3].strip()
-        infile.close()
-        for a in archs:
-            tarball = "%s/%s_%s.tgz"%(pbdir, branchstr, a.strip())
-            if not(os.path.isfile(tarball)):
-                createPbTar = ('sudo pbuilder --create --distribution %s --mirror %s --components "%s" --architecture %s --debootstrapopts "--keyring=%s" --basetgz %s'%
-                        (branchstr, mirror, components, a, keyringuse, tarball))
-                print "Creating tarball %s"%(tarball)
-                os.system(createPbTar)
-            else:
-                print "Tarball %s exists"%(tarball)
-                if (args.update):
-                    print "Updating %s as requested" %(tarball)
-                    updatePbTar = ('sudo pbuilder --update --basetgz %s'%(tarball))
-                    os.system(updatePbTar)
-            
-            # Creating dir for building
-            builddirup="%s_%s/"%(branchstr, a)
-            builddirdeb="%s/build/"%(builddirup)
-            builddirres="%s/result/"%(builddirup)
-            shutil.rmtree(builddirdeb,ignore_errors=True)
-            shutil.copytree(gitupsdir, builddirdeb )
-            shutil.rmtree(builddirdeb+".git")
-            # Get package version
-            versiondebian = repoups.git.describe()
-
-            # Get package name
-            infilepname = open(gitdebdir+"/changelog"); sourcePackName = infilepname.readlines()[0].split()[0]
-            print sourcePackName
-
-            os.system('cd %s; apack %s_%s.orig.tar.xz build'%(builddirup,sourcePackName,versiondebian))
-            shutil.copytree(gitdebdir, builddirdeb+"/debian")
-
-            os.system('sed -i.bak -e s/VERSION/%s/ -e s/DISTRIBUTION/%s/ %s/debian/changelog'%(versiondebian,branch,builddirdeb))
-            os.system('cd %s; dpkg-source -b -I build'%(builddirup))
-            os.mkdir(builddirres)
-            print "Building package %s_%s"%(sourcePackName, versiondebian)
-            buildPackage = ('sudo pbuilder --build --architecture %s --basetgz %s --logfile %s/pbuilder.log --debbuildopts "-j%d" --buildresult %s %s/*.dsc'%
-                (a, tarball, builddirup, jobsNumber, builddirres, builddirup))
-            print buildPackage
-            os.system(buildPackage)
-            shutil.rmtree(builddirdeb)
-            exit(0)
-

=== added file 'scripts/ppa/ppa.config'
--- scripts/ppa/ppa.config	1970-01-01 00:00:00 +0000
+++ scripts/ppa/ppa.config	2013-12-20 15:10:54 +0000
@@ -0,0 +1,31 @@
+# git debian-directory
+/home/USER/dem/yade/yadedaily/
+
+# directory, where will be created pbuilder tarballs
+/home/USER/dem/yade/ppa/pbuilder_new
+
+# git upstream-directrory
+/home/USER/dem/yade/trunk
+
+# user
+USER
+
+# group
+USER
+
+# name of dput ppa
+mini
+
+# Key to sign packages
+AA915EEB
+
+# Path to passphrase key
+/home/USER/dem/yade/ppa/gpg/pwdonly
+
+# Path to key secret part
+/home/USER/dem/yade/ppa/gpg/yadedev_sec.gpg
+
+# Path to archive (deb-repo)
+/home/USER/M/Temp/archive
+
+