← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 1719: ef2_Sphere_Sphere_Dem3Dof: change meaning of distanceFactor, see docs (if < 0, equilibrium is sum...

 

------------------------------------------------------------
revno: 1719
committer: Václav Šmilauer <vaclav@flux>
branch nick: trunk
timestamp: Sat 2009-08-22 20:21:25 +0200
message:
  ef2_Sphere_Sphere_Dem3Dof: change meaning of distanceFactor, see docs (if < 0, equilibrium is sum of radii, otherwise the initial distance; defaults to -1). Renamed to distFactor, to break old code intentionally
  InteractingSphere2AABB: allow negative aabbEnlargeFactor, which doesn't scale aabb at all (same as if it is 1.)
  yade-multi: use the first non-blank line as column headings (not necessarily the first line of the file, as is used to be)
  SpatialQuickSortCollider: fix clearing interaction with openMP
  examples/concrete/uniaxial: move files around, add confinement and docs; remove examples/concrete/pack since not in the pack module (an example should be given, though)
  examples/collider-perf: remove PersistentSAPCollider, add InsertionSortCollide with strides, but commented out since no effect at hthe beginning of simulation
  PeriodicInsertionSortCollider: remove unnecessary (hopefully) condition that would abort in scripts/test/periodic-simple.py
removed:
  examples/concrete/pack/
  examples/concrete/pack/mk-pack.py
  examples/concrete/uniaxial/
added:
  examples/concrete/README
renamed:
  examples/concrete/uniaxial/rb.py => examples/concrete/uniax.py
modified:
  .bzrignore
  core/InteractionContainer.cpp
  core/InteractionContainer.hpp
  examples/collider-perf/README
  examples/collider-perf/mkGraph.py
  examples/collider-perf/perf.py
  examples/collider-perf/perf.table
  examples/dynamic_simulation_tests/ringCundallDamping.py
  examples/dynamic_simulation_tests/ringSimpleViscoelastic.py
  extra/PeriodicInsertionSortCollider.cpp
  gui/py/yade-multi
  pkg/common/Engine/EngineUnit/InteractingSphere2AABB.cpp
  pkg/common/Engine/EngineUnit/InteractingSphere2AABB.hpp
  pkg/common/Engine/StandAloneEngine/SpatialQuickSortCollider.cpp
  pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp
  pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.hpp
  py/utils.py
  scripts/test/collider-stride-triax.py
  examples/concrete/uniax.py


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

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription.
=== modified file '.bzrignore'
--- .bzrignore	2009-08-20 19:55:52 +0000
+++ .bzrignore	2009-08-22 18:21:25 +0000
@@ -3,3 +3,8 @@
 scons.profile-*
 .project
 ./doc/doxygen
+VERSION
+yade.1
+debian/changelog
+debian/control
+doc/epydoc

=== modified file 'core/InteractionContainer.cpp'
--- core/InteractionContainer.cpp	2009-07-17 20:50:55 +0000
+++ core/InteractionContainer.cpp	2009-08-22 18:21:25 +0000
@@ -20,6 +20,14 @@
 	#endif
 }
 
+void InteractionContainer::clearPendingErase(){
+	#ifdef YADE_OPENMP
+		FOREACH(list<bodyIdPair>& pendingErase, threadsPendingErase){
+	#endif
+			pendingErase.clear();
+		}
+}
+
 int InteractionContainer::unconditionalErasePending(){
 	int ret=0;
 	#ifdef YADE_OPENMP

=== modified file 'core/InteractionContainer.hpp'
--- core/InteractionContainer.hpp	2009-08-06 21:05:28 +0000
+++ core/InteractionContainer.hpp	2009-08-22 18:21:25 +0000
@@ -135,6 +135,13 @@
 			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.
 

=== modified file 'examples/collider-perf/README'
--- examples/collider-perf/README	2009-05-22 21:06:02 +0000
+++ examples/collider-perf/README	2009-08-22 18:21:25 +0000
@@ -1,21 +1,28 @@
-This example tests performance of PersistentSAPCollider and SpatialQuickSortCollider
-and was basis for http://yade.wikia.com/wiki/Colliders_performace .
+This example tests performance of InsertionSortCollider (with and without stride) and
+SpatialQuickSortCollider and was basis for http://yade.wikia.com/wiki/Colliders_performace,
+which features now-removed PersistentSAPCollider as well.
 
 To run the test, say:
 
  yade-trunk-multi perf.table perf.py
 
-It will take time to finish. To get graphs from the generated log files, say
+It will take time to finish. To collet results and get graphs from the generated log files, say
 
  python mkGraph.py *.log
 
-To see other results, log files are named like perf.64k.log (64k spheres with
-PersistentSAPCollider), perf.32k.q.log (32k spheres, SpatialQuickSortCollider) etc.
+To see other results, log files are named like perf.64k.q.log (64k spheres with
+SpatialQuickSortCollider), perf.32k.i.log (32k spheres, InsertionSortCollider),
+perf.40k.is.log (InsertionSortCollider with stride) etc.
 
 1. File with nSpheres spheres (loose packing) is generated first, it if doesn't exist yet.
    This can take a few minutes, but is done only the first time for the particular sphere
 	number.
+
 2. First iteration on the scene (TriaxialTest and the selected collider) with timings is
    done and timing.stats() printed (appears in the log file).
+
 3. Another 100 iterations are measured with timing.stats(), after which the test exits.
 
+(Note: InsertionSortCollider with stride is currently commented out in the table,
+as striding is not effective until later during the simulation.)
+

=== modified file 'examples/collider-perf/mkGraph.py'
--- examples/collider-perf/mkGraph.py	2009-05-24 08:19:26 +0000
+++ examples/collider-perf/mkGraph.py	2009-08-22 18:21:25 +0000
@@ -1,5 +1,5 @@
 #encoding: utf-8
-dta={'QS':{},'SAP':{},'IS':{}}
+dta={'QS':{},'IS':{},'ISS':{}}
 import sys
 for f in sys.argv[1:]:
 	print f,'',
@@ -7,7 +7,8 @@
 	assert(N[-1]=='k'); N=1000*int(N[:-1])
 	if '.q.' in f: collider='QS'
 	elif '.i.' in f: collider='IS'
-	else: collider='SAP'
+	elif '.is.' in f: collider='ISS'
+	else: raise RuntimeError("Unknown collider type for file "+f)
 	for l in open(f):
 		if 'Collider' in l:
 			t=l.split()[2]; assert(t[-2:]=='us'); t=float(t[:-2])/1e6
@@ -15,25 +16,23 @@
 			else: dta[collider][N]+=[t*0.01] # the second time is per 100 iterations
 print 
 
-SAP_N=dta['SAP'].keys(); SAP_N.sort()
+ISS_N=dta['ISS'].keys(); ISS_N.sort()
 QS_N=dta['QS'].keys(); QS_N.sort()
 IS_N=dta['IS'].keys(); IS_N.sort()
-SAPinit=[dta['SAP'][N][0] for N in SAP_N]; SAPstep=[dta['SAP'][N][1] for N in SAP_N]
+ISSinit=[dta['ISS'][N][0] for N in ISS_N]; ISSstep=[dta['ISS'][N][1] for N in ISS_N]
 QSinit=[dta['QS'][N][0] for N in QS_N]; QSstep=[dta['QS'][N][1] for N in QS_N]
 ISinit=[dta['IS'][N][0] for N in IS_N]; ISstep=[dta['IS'][N][1] for N in IS_N]
 from pylab import *
-plot(SAP_N,SAPinit,'m')
-plot(IS_N,ISinit,'y')
+plot(IS_N,ISinit,'y',ISS_N,ISSinit)
 gca().set_yscale('log')
 xlabel("Number of spheres")
-ylabel(u"Log (!) time for the 1st SAP collider step [s]")
-title("SAP vs. QuickSort colliders performance")
-legend(('SAP init','IS init'),'upper left')
-
+ylabel(u"Log time for the 1st collider step [s]")
+title("Colliders performance (QS=QuickSoft, IS=InsertionSort, IS/s=IS+stride)")
+legend(('IS init','IS/s init',),'upper left')
 ax2=twinx()
-plot(SAP_N,SAPstep,'r-',IS_N,ISstep,'k-',QS_N,QSstep,'g-',QS_N,QSinit,'b-')
+plot(IS_N,ISstep,'k-',ISS_N,ISSstep,'r-',QS_N,QSstep,'g-',QS_N,QSinit,'b-')
 ylabel(u"Linear time per 1 step [s]")
-legend(('SAP step','InsertionSort step','QuickSort step','QuickSort init'),'right')
+legend(('IS step','IS/s step','QS step','QS init'),'right')
 grid()
 savefig('colliders.svg')
 show()

=== modified file 'examples/collider-perf/perf.py'
--- examples/collider-perf/perf.py	2009-03-08 21:15:35 +0000
+++ examples/collider-perf/perf.py	2009-08-22 18:21:25 +0000
@@ -1,12 +1,14 @@
 
-utils.readParamsFromTable(nSpheres=8000,collider='PersistentSAPCollider',noTableOk=True)
+utils.readParamsFromTable(nSpheres=8000,collider='InsertionSortCollider',noTableOk=True)
 # name of file containing sphere packing with given number of spheres
 spheresFile="packing-%dk.spheres"%(nSpheres/1000)
 
+fast='@stride' in collider
+
 import os
 if not os.path.exists(spheresFile):
 	print "Generating packing"
-	p=Preprocessor('TriaxialTest',{'numberOfGrains':nSpheres,'radiusMean':1e-3,'lowerCorner':[0,0,0],'upperCorner':[1,1,1]})
+	p=TriaxialTest(numberOfGrains=nSpheres,radiusMean=1e-3,lowerCorner=[0,0,0],upperCorner=[1,1,1],noFiles=True)
 	p.load()
 	utils.spheresToFile(spheresFile)
 	O.reset()
@@ -16,15 +18,16 @@
 from yade import timing
 O.timingEnabled=True
 
-p=Preprocessor('TriaxialTest',{'importFilename':spheresFile}).load()
+TriaxialTest(importFilename=spheresFile,fast=fast,noFiles=True).load()
 O.dt=utils.PWaveTimeStep()
-utils.replaceCollider(StandAloneEngine(collider))
-
-mem0=utils.vmData()
+isc=O.engines[2]
+isc['sweepLength']=1e-1
+
+if not fast: utils.replaceCollider(StandAloneEngine(collider))
+
 O.step()
 timing.stats()
-print 'Extra memory:',utils.vmData()-mem0,'kB'
 timing.reset()
-O.run(100,True)
+O.run(200,True)
 timing.stats()
 quit()

=== modified file 'examples/collider-perf/perf.table'
--- examples/collider-perf/perf.table	2009-05-29 13:35:22 +0000
+++ examples/collider-perf/perf.table	2009-08-22 18:21:25 +0000
@@ -1,77 +1,76 @@
 !OMP_NUM_THREADS description nSpheres collider
-3 128k 128000 'PersistentSAPCollider'
-3 96k 96000 'PersistentSAPCollider'
-3 64k 64000 'PersistentSAPCollider'
-3 56k 56000 'PersistentSAPCollider'
-3 48k 48000 'PersistentSAPCollider'
-3 40k 40000 'PersistentSAPCollider'
-3 36k 36000 'PersistentSAPCollider'
-3 32k 32000 'PersistentSAPCollider'
-3 28k 28000 'PersistentSAPCollider'
-3 24k 24000 'PersistentSAPCollider'
-3 20k 20000 'PersistentSAPCollider'
-3 18k 18000 'PersistentSAPCollider'
-3 16k 16000 'PersistentSAPCollider'
-3 14k 14000 'PersistentSAPCollider'
-3 12k 12000 'PersistentSAPCollider'
-3 10k 10000 'PersistentSAPCollider'
-3 9k 9000 'PersistentSAPCollider'
-3 8k 8000 'PersistentSAPCollider'
-3 7k 7000 'PersistentSAPCollider'
-3 6k 6000 'PersistentSAPCollider'
-3 5k 5000 'PersistentSAPCollider'
-3 4k 4000 'PersistentSAPCollider'
-3 3k 3000 'PersistentSAPCollider'
-3 2k 2000 'PersistentSAPCollider'
-3 1k 1000 'PersistentSAPCollider'
-3 128k.q 128000 'SpatialQuickSortCollider'
-3 96k.q 96000 'SpatialQuickSortCollider'
-3 64k.q 64000 'SpatialQuickSortCollider'
-3 56k.q 56000 'SpatialQuickSortCollider'
-3 48k.q 48000 'SpatialQuickSortCollider'
-3 40k.q 40000 'SpatialQuickSortCollider'
-3 36k.q 36000 'SpatialQuickSortCollider'
-3 32k.q 32000 'SpatialQuickSortCollider'
-3 28k.q 28000 'SpatialQuickSortCollider'
-3 24k.q 24000 'SpatialQuickSortCollider'
-3 20k.q 20000 'SpatialQuickSortCollider'
-3 18k.q 18000 'SpatialQuickSortCollider'
-3 16k.q 16000 'SpatialQuickSortCollider'
-3 14k.q 14000 'SpatialQuickSortCollider'
-3 12k.q 12000 'SpatialQuickSortCollider'
-3 10k.q 10000 'SpatialQuickSortCollider'
-3 9k.q 9000 'SpatialQuickSortCollider'
-3 8k.q 8000 'SpatialQuickSortCollider'
-3 7k.q 7000 'SpatialQuickSortCollider'
-3 6k.q 6000 'SpatialQuickSortCollider'
-3 5k.q 5000 'SpatialQuickSortCollider'
-3 4k.q 4000 'SpatialQuickSortCollider'
-3 3k.q 3000 'SpatialQuickSortCollider'
-3 2k.q 2000 'SpatialQuickSortCollider'
-3 1k.q 1000 'SpatialQuickSortCollider'
-1 128k.i1 128000 'InsertionSortCollider'
-3 128k.i 128000 'InsertionSortCollider'
-3 96k.i 96000 'InsertionSortCollider'
-3 64k.i 64000 'InsertionSortCollider'
-3 56k.i 56000 'InsertionSortCollider'
-3 48k.i 48000 'InsertionSortCollider'
-3 40k.i 40000 'InsertionSortCollider'
-3 36k.i 36000 'InsertionSortCollider'
-3 32k.i 32000 'InsertionSortCollider'
-3 28k.i 28000 'InsertionSortCollider'
-3 24k.i 24000 'InsertionSortCollider'
-3 20k.i 20000 'InsertionSortCollider'
-3 18k.i 18000 'InsertionSortCollider'
-3 16k.i 16000 'InsertionSortCollider'
-3 14k.i 14000 'InsertionSortCollider'
-3 12k.i 12000 'InsertionSortCollider'
-3 10k.i 10000 'InsertionSortCollider'
-3 9k.i 9000 'InsertionSortCollider'
-3 8k.i 8000 'InsertionSortCollider'
-3 7k.i 7000 'InsertionSortCollider'
-3 6k.i 6000 'InsertionSortCollider'
-3 5k.i 5000 'InsertionSortCollider'
-3 4k.i 4000 'InsertionSortCollider'
-3 3k.i 3000 'InsertionSortCollider'
-3 2k.i 2000 'InsertionSortCollider'
-3 1k.i 1000 'InsertionSortCollider'
+4 128k.q 128000 'SpatialQuickSortCollider'
+4 96k.q 96000 'SpatialQuickSortCollider'
+4 64k.q 64000 'SpatialQuickSortCollider'
+4 56k.q 56000 'SpatialQuickSortCollider'
+4 48k.q 48000 'SpatialQuickSortCollider'
+4 40k.q 40000 'SpatialQuickSortCollider'
+4 36k.q 36000 'SpatialQuickSortCollider'
+4 32k.q 32000 'SpatialQuickSortCollider'
+4 28k.q 28000 'SpatialQuickSortCollider'
+4 24k.q 24000 'SpatialQuickSortCollider'
+4 20k.q 20000 'SpatialQuickSortCollider'
+4 18k.q 18000 'SpatialQuickSortCollider'
+4 16k.q 16000 'SpatialQuickSortCollider'
+4 14k.q 14000 'SpatialQuickSortCollider'
+4 12k.q 12000 'SpatialQuickSortCollider'
+4 10k.q 10000 'SpatialQuickSortCollider'
+4 9k.q 9000 'SpatialQuickSortCollider'
+4 8k.q 8000 'SpatialQuickSortCollider'
+4 7k.q 7000 'SpatialQuickSortCollider'
+4 6k.q 6000 'SpatialQuickSortCollider'
+4 5k.q 5000 'SpatialQuickSortCollider'
+4 4k.q 4000 'SpatialQuickSortCollider'
+4 3k.q 3000 'SpatialQuickSortCollider'
+4 2k.q 2000 'SpatialQuickSortCollider'
+4 1k.q 1000 'SpatialQuickSortCollider'
+4 128k.i 128000 'InsertionSortCollider'
+4 96k.i 96000 'InsertionSortCollider'
+4 64k.i 64000 'InsertionSortCollider'
+4 56k.i 56000 'InsertionSortCollider'
+4 48k.i 48000 'InsertionSortCollider'
+4 40k.i 40000 'InsertionSortCollider'
+4 36k.i 36000 'InsertionSortCollider'
+4 32k.i 32000 'InsertionSortCollider'
+4 28k.i 28000 'InsertionSortCollider'
+4 24k.i 24000 'InsertionSortCollider'
+4 20k.i 20000 'InsertionSortCollider'
+4 18k.i 18000 'InsertionSortCollider'
+4 16k.i 16000 'InsertionSortCollider'
+4 14k.i 14000 'InsertionSortCollider'
+4 12k.i 12000 'InsertionSortCollider'
+4 10k.i 10000 'InsertionSortCollider'
+4 9k.i 9000 'InsertionSortCollider'
+4 8k.i 8000 'InsertionSortCollider'
+4 7k.i 7000 'InsertionSortCollider'
+4 6k.i 6000 'InsertionSortCollider'
+4 5k.i 5000 'InsertionSortCollider'
+4 4k.i 4000 'InsertionSortCollider'
+4 3k.i 3000 'InsertionSortCollider'
+4 2k.i 2000 'InsertionSortCollider'
+4 1k.i 1000 'InsertionSortCollider'
+#4 128k.is 128000 'InsertionSortCollider'
+#4 96k.is 96000 'InsertionSortCollider'
+#4 64k.is 64000 'InsertionSortCollider'
+#4 56k.is 56000 'InsertionSortCollider'
+#4 48k.is 48000 'InsertionSortCollider@stride'
+#4 40k.is 40000 'InsertionSortCollider@stride'
+#4 36k.is 36000 'InsertionSortCollider@stride'
+#4 32k.is 32000 'InsertionSortCollider@stride'
+#4 28k.is 28000 'InsertionSortCollider@stride'
+#4 24k.is 24000 'InsertionSortCollider@stride'
+#4 20k.is 20000 'InsertionSortCollider@stride'
+#4 18k.is 18000 'InsertionSortCollider@stride'
+#4 16k.is 16000 'InsertionSortCollider@stride'
+#4 14k.is 14000 'InsertionSortCollider@stride'
+#4 12k.is 12000 'InsertionSortCollider@stride'
+#4 10k.is 10000 'InsertionSortCollider@stride'
+#4 9k.is 9000 'InsertionSortCollider@stride'
+#4 8k.is 8000 'InsertionSortCollider@stride'
+#4 7k.is 7000 'InsertionSortCollider@stride'
+#4 6k.is 6000 'InsertionSortCollider@stride'
+#4 5k.is 5000 'InsertionSortCollider@stride'
+#4 4k.is 4000 'InsertionSortCollider@stride'
+#4 3k.is 3000 'InsertionSortCollider@stride'
+#4 2k.is 2000 'InsertionSortCollider@stride'
+#4 1k.is 1000 'InsertionSortCollider@stride'

=== added file 'examples/concrete/README'
--- examples/concrete/README	1970-01-01 00:00:00 +0000
+++ examples/concrete/README	2009-08-22 18:21:25 +0000
@@ -0,0 +1,10 @@
+uniax.py shows uniaxiax tension/compression test on concrete specimen with
+optional confinement.
+
+Run using yade-multi and confined.table (see comments in that file) to run
+simulation with different confinement values.
+
+Run plain uniax.py to get one unconfined tension/compression simulation.
+Type yade.plot.plot() to see strain/stress plot during the simulation.
+
+See comments at the beginning of uniax.py for more information.

=== removed directory 'examples/concrete/pack'
=== removed file 'examples/concrete/pack/mk-pack.py'
--- examples/concrete/pack/mk-pack.py	2009-05-31 09:09:14 +0000
+++ examples/concrete/pack/mk-pack.py	1970-01-01 00:00:00 +0000
@@ -1,73 +0,0 @@
-from yade import log
-import shutil, tempfile
-#
-# Generate box or cylindrical packing that is rather compact using TriaxialTest.
-#
-
-# if non-negative, the resulting sample will be cylindrical; if < 0, generate box
-cylAxis=1
-# how many layers of average spheres to cut away from flat parts (relative to mean sphere radius); sphere center count
-cutoffFlat=3.5
-# how many layers of average spheres to cut away from round surfaces (relative to mean sphere radius); sphere centers count
-cutoffRound=2
-
-tt=TriaxialTest(
-	numberOfGrains=5000,
-	radiusMean=3e-4,
-	# this is just size ratio if radiusMean is specified
-	# if you comment out the line above, it will be the corner (before compaction) and radiusMean will be set accordingly
-	upperCorner=[2,4,2],
-	radiusStdDev=0, # all spheres exactly the same radius
-	
-	##
-	## no need to touch any the following, till the end of file
-	##
-	noFiles=True,
-	lowerCorner=[0,0,0],
-	sigmaIsoCompaction=1e7,
-	sigmaLateralConfinement=1e3,
-	StabilityCriterion=.05,
-	strainRate=.2,
-	fast=True,
-	maxWallVelocity=.1,
-	wallOversizeFactor=2,
-	autoUnload=True, # unload after isotropic compaction
-	autoCompressionActivation=False # stop once unloaded
-)
-
-tt.load()
-log.setLevel('TriaxialCompressionEngine',log.WARN)
-O.run() ## triax stops by itself once unloaded
-O.wait()
-
-# resulting specimen geometry
-ext=utils.aabbExtrema()
-rSphere=tt['radiusMean']
-
-outFile=tempfile.NamedTemporaryFile(delete=False).name
-
-if cylAxis<0: # box-shaped packing
-	aabbMin,aabbMax=tuple([ext[0][i]+rSphere*cutoffFlat for i in 0,1,2]),tuple([ext[1][i]-rSphere*cutoffFlat for i in 0,1,2])
-	def isInBox(id):
-		pos=O.bodies[id].phys.pos
-		return utils.ptInAABB(pos,aabbMin,aabbMax)
-	nSpheres=utils.spheresToFile(outFile,consider=isInBox)
-else: # cylinger packing
-	mid   =[.5*(ext[1][i]+ext[0][i]) for i in [0,1,2]]
-	extent=[.5*(ext[1][i]-ext[0][i]) for i in [0,1,2]]
-	ax1,ax2=(cylAxis+1)%3,(cylAxis+2)%3
-	cylRadius=min(extent[ax1],extent[ax2])-cutoffRound*rSphere
-	cylHalfHt=extent[cylAxis]-cutoffFlat*rSphere
-	def isInCyl(id):
-		pos=O.bodies[id].phys.pos
-		axisDist=sqrt((pos[ax1]-mid[ax1])**2+(pos[ax2]-mid[ax2])**2)
-		if axisDist>cylRadius: return False
-		axialDist=abs(pos[cylAxis]-mid[cylAxis])
-		if axialDist>cylHalfHt: return False
-		return True
-	nSpheres=utils.spheresToFile(outFile,consider=isInCyl)
-
-outFile2='pack-%d-%s.spheres'%(nSpheres,'box' if cylAxis<0 else 'cyl')
-shutil.move(outFile,outFile2)
-print nSpheres,'spheres written to',outFile2
-quit()

=== renamed file 'examples/concrete/uniaxial/rb.py' => 'examples/concrete/uniax.py'
--- examples/concrete/uniaxial/rb.py	2009-08-04 07:46:09 +0000
+++ examples/concrete/uniax.py	2009-08-22 18:21:25 +0000
@@ -55,6 +55,9 @@
 
 	specimenLength=.2,
 	sphereRadius=3.5e-3,
+
+	# isotropic confinement (should be negative)
+	isoPrestress=0,
 )
 
 if 'description' in O.tags.keys(): O.tags['id']=O.tags['id']+O.tags['description']
@@ -63,7 +66,7 @@
 # make geom; the dimensions are hard-coded here; could be in param table if desired
 # z-oriented hyperboloid, length 20cm, diameter 10cm, skirt 8cm
 # using spheres 7mm of diameter
-spheres=pack.triaxialPack(pack.inHyperboloid((0,0,-.5*specimenLength),(0,0,.5*specimenLength),.25*specimenLength,.2*specimenLength),radius=sphereRadius,memoizeDb='/tmp/triaxPackCache.sqlite',young=young,poisson=poisson,frictionAngle=frictionAngle,physParamsClass='CpmMat',density=density)
+spheres=pack.randomDensePack(pack.inHyperboloid((0,0,-.5*specimenLength),(0,0,.5*specimenLength),.25*specimenLength,.2*specimenLength),spheresInCell=2000,radius=sphereRadius,memoizeDb='/tmp/triaxPackCache.sqlite',young=young,poisson=poisson,frictionAngle=frictionAngle,physParamsClass='CpmMat',density=density)
 O.bodies.append(spheres)
 bb=utils.uniaxialTestFeatures()
 negIds,posIds,axis,crossSectionArea=bb['negIds'],bb['posIds'],bb['axis'],bb['area']
@@ -79,8 +82,8 @@
 	BoundingVolumeMetaEngine([InteractingSphere2AABB(aabbEnlargeFactor=intRadius,label='is2aabb'),MetaInteractingGeometry2AABB()]),
 	InsertionSortCollider(),
 	InteractionDispatchers(
-		[ef2_Sphere_Sphere_Dem3DofGeom(distanceFactor=intRadius,label='ss2d3dg')],
-		[Ip2_CpmMat_CpmMat_CpmPhys(sigmaT=sigmaT,relDuctility=relDuctility,epsCrackOnset=epsCrackOnset,G_over_E=G_over_E)],
+		[ef2_Sphere_Sphere_Dem3DofGeom(distFactor=intRadius,label='ss2d3dg')],
+		[Ip2_CpmMat_CpmMat_CpmPhys(sigmaT=sigmaT,relDuctility=relDuctility,epsCrackOnset=epsCrackOnset,G_over_E=G_over_E,isoPrestress=isoPrestress)],
 		[Law2_Dem3DofGeom_CpmPhys_Cpm()],
 	),
 	NewtonsDampedLaw(damping=damping,label='damper'),
@@ -91,7 +94,8 @@
 ]
 O.miscParams=[GLDrawCpmPhys(dmgLabel=False,colorStrain=False,epsNLabel=False,epsT=False,epsTAxes=False,normal=False,contactLine=True)]
 
-plot.plots={'eps':('sigma','sigma.25','sigma.50','sigma.75')}
+# plot stresses in ¼, ½ and ¾ if desired as well; too crowded in the graph that includes confinement, though
+plot.plots={'eps':('sigma',)} #'sigma.25','sigma.50','sigma.75')}
 plot.maxDataLen=4000
 
 O.saveTmp('initial');
@@ -116,8 +120,8 @@
 	print "init done, will now run."
 	O.step(); O.step(); # to create initial contacts
 	# now reset the interaction radius and go ahead
-	ss2d3dg['distanceFactor']=1.
-	is2aabb['aabbEnlargeFactor']=1.
+	ss2d3dg['distFactor']=-1.
+	is2aabb['aabbEnlargeFactor']=-1.
 	O.run()
 
 def stopIfDamaged():
@@ -129,7 +133,7 @@
 	if extremum==0: return
 	print O.tags['id'],mode,strainer['strain'],sigma[-1]
 	import sys;	sys.stdout.flush()
-	if abs(sigma[-1]/extremum)<minMaxRatio:
+	if abs(sigma[-1]/extremum)<minMaxRatio or abs(strainer['strain'])>5e-3:
 		if mode=='tension' and doModes & 2: # only if compression is enabled
 			mode='compression'
 			print "Damaged, switching to compression... "; O.pause()
@@ -149,16 +153,15 @@
 			sys.exit(0)
 		
 def addPlotData():
-	yade.plot.addData({'t':O.time,'i':O.iter,'eps':strainer['strain'],'sigma':strainer['avgStress'],
-		'sigma.25':utils.forcesOnCoordPlane(coord_25,axis)[axis]/area_25,
-		'sigma.50':utils.forcesOnCoordPlane(coord_50,axis)[axis]/area_50,
-		'sigma.75':utils.forcesOnCoordPlane(coord_75,axis)[axis]/area_75,
+	yade.plot.addData({'t':O.time,'i':O.iter,'eps':strainer['strain'],'sigma':strainer['avgStress']+isoPrestress,
+		'sigma.25':utils.forcesOnCoordPlane(coord_25,axis)[axis]/area_25+isoPrestress,
+		'sigma.50':utils.forcesOnCoordPlane(coord_50,axis)[axis]/area_50+isoPrestress,
+		'sigma.75':utils.forcesOnCoordPlane(coord_75,axis)[axis]/area_75+isoPrestress,
 		})
 
-
-
 initTest()
-#while True: time.sleep(1)
+# sleep forever if run by yade-multi, exit is called from stopIfDamaged
+if os.environ.has_key('PARAM_TABLE'): time.sleep(1e12)
 
 
 

=== removed directory 'examples/concrete/uniaxial'
=== modified file 'examples/dynamic_simulation_tests/ringCundallDamping.py'
--- examples/dynamic_simulation_tests/ringCundallDamping.py	2009-08-10 16:59:33 +0000
+++ examples/dynamic_simulation_tests/ringCundallDamping.py	2009-08-22 18:21:25 +0000
@@ -80,7 +80,7 @@
 
 for b in o.bodies:
     if b.shape.name=='Sphere':
-        b.phys['blockedDOFs']=4 # blocked movement along Z
+        b.phys.blockedDOFs=['z'] # blocked movement along Z
 
 o.dt=0.2*utils.PWaveTimeStep()
 

=== modified file 'examples/dynamic_simulation_tests/ringSimpleViscoelastic.py'
--- examples/dynamic_simulation_tests/ringSimpleViscoelastic.py	2009-08-10 16:59:33 +0000
+++ examples/dynamic_simulation_tests/ringSimpleViscoelastic.py	2009-08-22 18:21:25 +0000
@@ -85,7 +85,7 @@
 
 for b in o.bodies:
     if b.shape.name=='Sphere':
-        b.phys['blockedDOFs']=4 # blocked movement along Z
+        b.phys.blockedDOFs=['z']
 
 o.dt=0.2*tc
 

=== modified file 'extra/PeriodicInsertionSortCollider.cpp'
--- extra/PeriodicInsertionSortCollider.cpp	2009-08-22 15:05:20 +0000
+++ extra/PeriodicInsertionSortCollider.cpp	2009-08-22 18:21:25 +0000
@@ -137,7 +137,9 @@
 		int j=i_1; Bound vi=v[i];  const bool viHasBB=vi.flags.hasBB;
 		while(v[j].coord>vi.coord + /* wrap for elt just below split */ (v.norm(j+1)==loIdx ? v.cellDim : 0)){
 			long j1=v.norm(j+1);
-			if (v[j].coord>v.cellMax+v.cellDim){
+			// OK, now if many bodies move at the same pace through the cell and at one point, there is inversion,
+			// this can happen without any side-effects
+			if (false && v[j].coord>v.cellMax+v.cellDim){
 				// this condition is not strictly necessary, but the loop of insertionSort would have to run more times.
 				// Since size of particle is required to be < .5*cellDim, this would mean simulation explosion anyway
 				LOG_FATAL("Body #"<<v[j].id<<" going faster than 1 cell in one step? Not handled.");

=== modified file 'gui/py/yade-multi'
--- gui/py/yade-multi	2009-05-22 21:06:02 +0000
+++ gui/py/yade-multi	2009-08-22 18:21:25 +0000
@@ -124,11 +124,12 @@
 print "Will run `%s' on `%s' with nice value %d, output redirected to `%s', %d jobs at a time."%(executable,simul,nice,logFormat,maxJobs)
 
 ll=[re.sub('\s*#.*','',l) for l in ['']+open(table,'r').readlines()] # remove comments
-availableLines=[i for i in range(len(ll)) if not re.match(r'^\s*(#.*)?$',ll[i][:-1]) and i>1]
-
+availableLines=[i for i in range(len(ll)) if not re.match(r'^\s*(#.*)?$',ll[i][:-1])]
+# first non-blank line are column headings
+headings=ll[availableLines[0]].split()
+availableLines=availableLines[1:]
 # read actual data
 values={}
-headings=ll[1].split()
 for l in availableLines:
 	val={}
 	for i in range(len(headings)):
@@ -185,7 +186,8 @@
 	nSlots=1
 	for col,head in enumerate(headings):
 		if head=='!EXEC': executable=values[l][col]
-		if head=='!OMP_NUM_THREADS': nSlots=int(values[l][col])
+		if head=='!OMP_NUM_THREADS':
+			nSlots=int(values[l][col]); maxCpu=getNumCores()
 		if head[0]=='!': envVars+=['%s=%s'%(head[1:],values[l][col])]
 	if nSlots>maxJobs: logging.warning('WARNING: job #%d wants %d slots but only %d are available'%(i,nSlots,maxJobs))
 	jobs.append(JobInfo(i,idStrings[l] if idStrings else '#'+str(i),'PARAM_TABLE=%s:%d %s nice -n %d %s -N PythonUI -- -n -x %s > %s 2>&1'%(table,l,' '.join(envVars),nice,executable,simul,pipes.quote(logFile)),logFile,nSlots))

=== modified file 'pkg/common/Engine/EngineUnit/InteractingSphere2AABB.cpp'
--- pkg/common/Engine/EngineUnit/InteractingSphere2AABB.cpp	2009-08-19 12:00:35 +0000
+++ pkg/common/Engine/EngineUnit/InteractingSphere2AABB.cpp	2009-08-22 18:21:25 +0000
@@ -14,7 +14,7 @@
 	InteractingSphere* sphere = static_cast<InteractingSphere*>(cm.get());
 	AABB* aabb = static_cast<AABB*>(bv.get());
 	aabb->center = se3.position;
-	aabb->halfSize = aabbEnlargeFactor*Vector3r(sphere->radius,sphere->radius,sphere->radius);
+	aabb->halfSize = (aabbEnlargeFactor>0?aabbEnlargeFactor:1.)*Vector3r(sphere->radius,sphere->radius,sphere->radius);
 	
 	aabb->min = aabb->center-aabb->halfSize;
 	aabb->max = aabb->center+aabb->halfSize;	

=== modified file 'pkg/common/Engine/EngineUnit/InteractingSphere2AABB.hpp'
--- pkg/common/Engine/EngineUnit/InteractingSphere2AABB.hpp	2009-05-01 14:47:26 +0000
+++ pkg/common/Engine/EngineUnit/InteractingSphere2AABB.hpp	2009-08-22 18:21:25 +0000
@@ -13,7 +13,7 @@
 class InteractingSphere2AABB : public BoundingVolumeEngineUnit
 {
 	public :
-		InteractingSphere2AABB(): aabbEnlargeFactor(1.) {}
+		InteractingSphere2AABB(): aabbEnlargeFactor(-1.) {}
 		void go(const shared_ptr<InteractingGeometry>& cm, shared_ptr<BoundingVolume>& bv, const Se3r& se3, const Body*);
 		double aabbEnlargeFactor;
 	FUNCTOR2D(InteractingSphere,AABB);

=== modified file 'pkg/common/Engine/StandAloneEngine/SpatialQuickSortCollider.cpp'
--- pkg/common/Engine/StandAloneEngine/SpatialQuickSortCollider.cpp	2009-08-03 10:02:11 +0000
+++ pkg/common/Engine/StandAloneEngine/SpatialQuickSortCollider.cpp	2009-08-22 18:21:25 +0000
@@ -28,7 +28,7 @@
 	const shared_ptr<BodyContainer>& bodies = ncb->bodies;
 
 	// This collider traverses all interactions at every step, therefore interactions that were reset() will be deleted automatically as needed
-	ncb->interactions->pendingErase.clear();
+	ncb->interactions->clearPendingErase();
 
 	size_t nbElements=bodies->size();
 	if (nbElements!=rank.size())

=== modified file 'pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp'
--- pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp	2009-08-09 16:17:53 +0000
+++ pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.cpp	2009-08-22 18:21:25 +0000
@@ -152,7 +152,7 @@
 bool ef2_Sphere_Sphere_Dem3DofGeom::go(const shared_ptr<InteractingGeometry>& cm1, const shared_ptr<InteractingGeometry>& cm2, const Se3r& se31, const Se3r& se32, const shared_ptr<Interaction>& c){
 	InteractingSphere *s1=static_cast<InteractingSphere*>(cm1.get()), *s2=static_cast<InteractingSphere*>(cm2.get());
 	Vector3r normal=se32.position-se31.position;
-	Real penetrationDepthSq=pow(distanceFactor*(s1->radius+s2->radius),2)-normal.SquaredLength();
+	Real penetrationDepthSq=pow((distFactor>0?distFactor:1.)*(s1->radius+s2->radius),2)-normal.SquaredLength();
 	if (penetrationDepthSq<0 && !c->isReal()){
 		return false;
 	}
@@ -164,7 +164,7 @@
 		ss=shared_ptr<Dem3DofGeom_SphereSphere>(new Dem3DofGeom_SphereSphere());
 		c->interactionGeometry=ss;
 		// constants
-		if(distanceFactor>1) ss->refLength=dist;
+		if(distFactor>0) ss->refLength=dist;
 		else ss->refLength=s1->radius+s2->radius;
 		ss->refR1=s1->radius; ss->refR2=s2->radius;
 		Real penetrationDepth=s1->radius+s2->radius-ss->refLength;

=== modified file 'pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.hpp'
--- pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.hpp	2009-08-21 10:06:00 +0000
+++ pkg/dem/DataClass/InteractionGeometry/Dem3DofGeom_SphereSphere.hpp	2009-08-22 18:21:25 +0000
@@ -61,14 +61,14 @@
 	public:
 		virtual bool go(const shared_ptr<InteractingGeometry>& cm1, const shared_ptr<InteractingGeometry>& cm2, const Se3r& se31, const Se3r& se32, const shared_ptr<Interaction>& c);
 		virtual bool goReverse(	const shared_ptr<InteractingGeometry>&, const shared_ptr<InteractingGeometry>&, const Se3r&, const Se3r&, const shared_ptr<Interaction>&){throw runtime_error("goReverse on symmetric functor should never be called!");}
-		//! Factor of sphere radius such that sphere "touch" if their centers are not further than distanceFactor*(r1+r2); defaults to 1.
-		//! If >1, equilibrium distance is the one when spheres get into initial contact; it is the sum of their radii otherwise.
-		Real distanceFactor;
-		ef2_Sphere_Sphere_Dem3DofGeom(): distanceFactor(1.) {}
+		//! Factor of sphere radius such that sphere "touch" if their centers are not further than distFactor*(r1+r2);
+		//! if negative, equilibrium distance is the sum of the sphere's radii, which is the default.
+		Real distFactor;
+		ef2_Sphere_Sphere_Dem3DofGeom(): distFactor(-1.) {}
 	FUNCTOR2D(InteractingSphere,InteractingSphere);
 	DEFINE_FUNCTOR_ORDER_2D(InteractingSphere,InteractingSphere);
 	REGISTER_CLASS_AND_BASE(ef2_Sphere_Sphere_Dem3DofGeom,InteractionGeometryEngineUnit);
-	REGISTER_ATTRIBUTES(InteractionGeometryEngineUnit,(distanceFactor));
+	REGISTER_ATTRIBUTES(InteractionGeometryEngineUnit,(distFactor));
 	DECLARE_LOGGER;
 };
 REGISTER_SERIALIZABLE(ef2_Sphere_Sphere_Dem3DofGeom);

=== modified file 'py/utils.py'
--- py/utils.py	2009-08-12 20:12:21 +0000
+++ py/utils.py	2009-08-22 18:21:25 +0000
@@ -264,7 +264,7 @@
 	count=0
 	for b in o.bodies:
 		if not b.shape or not b.shape.name=='Sphere' or not consider(b.id): continue
-		out.write('%g\t%g\t%g\t%g\n'%(b.phys['se3'][0],b.phys['se3'][1],b.phys['se3'][2],b.shape['radius']))
+		out.write('%g\t%g\t%g\t%g\n'%(b.phys.pos[0],b.phys.pos[1],b.phys.pos[2],b.shape['radius']))
 		count+=1
 	out.close()
 	return count
@@ -376,9 +376,10 @@
 
 		The format of the file is as follows (commens starting with # and empty lines allowed)
 		
-		name1 name2 … # 0th line
-		val1  val2  … # 1st line
-		val2  val2  … # 2nd line
+		# commented lines allowed anywhere
+		name1 name2 … # first non-blank line are column headings
+		val1  val2  … # 1st parameter set
+		val2  val2  … # 2nd 
 		…
 
 	The name `description' is special and is assigned to Omega().tags['description']
@@ -394,7 +395,7 @@
 	o=Omega()
 	tagsParams=[]
 	dictDefaults,dictParams={},{}
-	import os, __builtin__
+	import os, __builtin__,re
 	if not tableFileLine and not os.environ.has_key('PARAM_TABLE'):
 		if not noTableOk: raise EnvironmentError("PARAM_TABLE is not defined in the environment")
 		o.tags['line']='l!'
@@ -405,7 +406,12 @@
 		tableFile,tableLine=env[0],env[1]
 		if len(env)>2: tableDesc=env[3]
 		o.tags['line']='l'+tableLine
-		ll=[l.split('#')[0] for l in ['']+open(tableFile).readlines()]; names=ll[1].split(); values=ll[int(tableLine)].split()
+		# the empty '#' line to make line number 1-based
+		ll=[l for l in ['#']+open(tableFile).readlines()]; values=ll[int(tableLine)].split('#')[0].split()
+		names=None
+		for l in ll:
+			if not re.match(r'^\s*(#.*)?$',l): names=l.split(); break
+		if not names: raise RuntimeError("No non-blank line (colum headings) found.");
 		assert(len(names)==len(values))
 		if 'description' in names: O.tags['description']=values[names.index('description')]
 		else:

=== modified file 'scripts/test/collider-stride-triax.py'
--- scripts/test/collider-stride-triax.py	2009-07-13 18:31:44 +0000
+++ scripts/test/collider-stride-triax.py	2009-08-22 18:21:25 +0000
@@ -3,8 +3,8 @@
 from yade import timing,log
 import os.path
 loadFrom='/tmp/triax.xml'
-if not os.path.exists(loadFrom):
-	TriaxialTest(numberOfGrains=20000,fast=True,noFiles=True).generate(loadFrom)
+#if not os.path.exists(loadFrom):
+TriaxialTest(numberOfGrains=2000,fast=True,noFiles=True).generate(loadFrom)
 O.load(loadFrom)
 log.setLevel('TriaxialCompressionEngine',log.WARN) # shut up
 log.setLevel('InsertionSortCollider',log.DEBUG)
@@ -15,9 +15,9 @@
 # use striding; say "if 0:" to disable striding and compare to regular runs
 if 1:
 	# length by which bboxes will be made larger
-	collider['sweepLength']=0.05*O.bodies[100].shape['radius']
+	collider['sweepLength']=.2*O.bodies[100].shape['radius']
 	# if this is enabled, bboxes will be enlarged based on velocity bin for each body
-	if 0:
+	if 1:
 		collider['nBins']=3
 		collider['binCoeff']=10
 		log.setLevel('VelocityBins',log.DEBUG)