← Back to team overview

yade-dev team mailing list archive

[svn] r1680 - in trunk: . core extra extra/clump extra/usct gui/py pkg/common/Engine/DeusExMachina pkg/common/Engine/MetaEngine pkg/common/Engine/StandAloneEngine pkg/dem/Engine/DeusExMachina pkg/dem/Engine/EngineUnit pkg/dem/Engine/StandAloneEngine

 

Author: eudoxos
Date: 2009-02-22 21:08:45 +0100 (Sun, 22 Feb 2009)
New Revision: 1680

Modified:
   trunk/SConstruct
   trunk/core/BexContainer.hpp
   trunk/core/Omega.hpp
   trunk/extra/Brefcom.cpp
   trunk/extra/clump/Shop.cpp
   trunk/extra/clump/Shop.hpp
   trunk/extra/usct/UniaxialStrainControlledTest.cpp
   trunk/gui/py/_utils.cpp
   trunk/gui/py/yadeControl.cpp
   trunk/pkg/common/Engine/DeusExMachina/GravityEngines.cpp
   trunk/pkg/common/Engine/MetaEngine/ConstitutiveLaw.hpp
   trunk/pkg/common/Engine/StandAloneEngine/PhysicalActionContainerInitializer.cpp
   trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp
   trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.cpp
   trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.hpp
   trunk/pkg/dem/Engine/EngineUnit/Spheres_Viscoelastic_SimpleViscoelasticContactLaw.cpp
   trunk/pkg/dem/Engine/StandAloneEngine/ElasticContactLaw.cpp
Log:
1. Add BexContainer (same interface, but separate implementation) in openMP flavor.
2. openmp=0 is the default for scons now (for some time), since openMP BexContainer gives about 7% slowdown and thus is not useful before at least some engines are parallelized as well.
3. Removed getting references to Force/Torque from BexContainer, since that breaks concurrency. Instead, addForce/addTorque must be used. If you need to read back with getForce/getTorque, you have to call sync() (expensive!!) beforehand, which will compute summary values for all bodies; if you forget, exception will be thrown. Note that sync() is invalidated at next write operation.
4. Adapted a few constitutive laws and other engines for the changes mentiones here.



Modified: trunk/SConstruct
===================================================================
--- trunk/SConstruct	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/SConstruct	2009-02-22 20:08:45 UTC (rev 1680)
@@ -102,8 +102,8 @@
 print '@@@ Using profile',profile,'('+optsFile+') @@@'
 
 # defaults for various profiles
-if profile=='default': defOptions={'debug':1,'variant':'','optimize':0,'openmp':True}
-elif profile=='opt': defOptions={'debug':0,'variant':'-opt','optimize':1,'openmp':True}
+if profile=='default': defOptions={'debug':1,'variant':'','optimize':0,'openmp':False}
+elif profile=='opt': defOptions={'debug':0,'variant':'-opt','optimize':1,'openmp':False}
 else: defOptions={'debug':0,'optimize':0,'variant':profile,'openmp':True}
 
 
@@ -390,7 +390,7 @@
 ### COMPILER
 if env['debug']: env.Append(CXXFLAGS='-ggdb3',CPPDEFINES=['YADE_DEBUG'])
 else: env.Append(CXXFLAGS='-O2')
-if env['openmp']: env.Append(CXXFLAGS='-fopenmp',LIBS='gomp')
+if env['openmp']: env.Append(CXXFLAGS='-fopenmp',LIBS='gomp',CPPDEFINES='YADE_OPENMP')
 if env['optimize']:
 	env.Append(CXXFLAGS=Split('-O3 -ffast-math -march=%s'%env['march']),
 		CPPDEFINES=[('YADE_CAST','static_cast'),('YADE_PTR_CAST','static_pointer_cast'),'NDEBUG'])

Modified: trunk/core/BexContainer.hpp
===================================================================
--- trunk/core/BexContainer.hpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/core/BexContainer.hpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -7,6 +7,83 @@
 // for body_id_t
 #include<yade/core/Interaction.hpp>
 
+#ifdef YADE_OPENMP
+
+#include<omp.h>
+
+class BexContainer{
+	private:
+		typedef std::vector<Vector3r> vvector;
+		std::vector<vvector> _forceData;
+		std::vector<vvector> _torqueData;
+		vvector _force, _torque;
+		size_t size;
+		int nThreads;
+		bool synced;
+		boost::mutex globalMutex;
+
+		inline void ensureSize(body_id_t id){
+			assert(nThreads>omp_get_thread_num());
+			if (size<=(size_t)id) resize(min((size_t)1.5*(id+100),(size_t)(id+2000)));
+		}
+
+		inline void ensureSynced(){ if(!synced) throw runtime_error("BexContainer not thread-synchronized; call sync() first!"); }
+	public:
+		BexContainer(): size(0), synced(true){
+			nThreads=omp_get_max_threads();
+			for(int i=0; i<nThreads; i++){
+				_forceData.push_back(vvector()); _torqueData.push_back(vvector());
+			}
+		}
+
+		/* To be benchmarked: sum thread data in getForce/getTorque upon request for each body individually instead of by the sync() function globally */
+		const Vector3r& getForce(body_id_t id)         { ensureSize(id); ensureSynced(); return _force[id]; }
+		void  addForce(body_id_t id, const Vector3r& f){ ensureSize(id); synced=false;   _forceData[omp_get_thread_num()][id]+=f;}
+		const Vector3r& getTorque(body_id_t id)        { ensureSize(id); ensureSynced(); return _torque[id]; }
+		void addTorque(body_id_t id, const Vector3r& f){ ensureSize(id); synced=false;   _torqueData[omp_get_thread_num()][id]+=f;}
+
+		/* Sum contributions from all threads, save to the 0th thread storage.
+		 * Locks globalMutex, since one thread modifies other threads' data.
+		 * Must be called before get* methods are used. Exception is thrown otherwise, since data are not consistent.
+		 */
+		inline void sync(){
+			if(synced) return;
+			boost::mutex::scoped_lock lock(globalMutex);
+			// #pragma omp parallel for private(sumF,sumT,thread);
+			for(size_t id=0; id<size; id++){
+				Vector3r sumF(Vector3r::ZERO), sumT(Vector3r::ZERO);
+				for(int thread=0; thread<omp_get_max_threads(); thread++){ sumF+=_forceData[thread][id]; sumT+=_torqueData[thread][id];}
+				_force[id]=sumF; _torque[id]=sumT;
+			}
+			synced=true;
+		}
+
+		/* Change size of containers (number of bodies).
+		 * Locks globalMutex, since on threads modifies other threads' data.
+		 * Called very rarely (a few times at the beginning of the simulation)
+		 */
+		void resize(size_t newSize){
+			boost::mutex::scoped_lock lock(globalMutex);
+			if(size>=newSize) return; // in case on thread was waiting for resize, but it was already satisfied by another one
+			for(int thread=0; thread<nThreads; thread++){
+				_forceData [thread].resize(newSize);
+				_torqueData[thread].resize(newSize);
+			}
+			_force.resize(newSize); _torque.resize(newSize);
+			size=newSize;
+		}
+
+		void reset(){
+			for(int thread=0; thread<nThreads; thread++){
+				memset(_forceData [thread][0], 0,sizeof(Vector3r)*size);
+				memset(_torqueData[thread][0],0,sizeof(Vector3r)*size);
+			}
+			memset(_force [0], 0,sizeof(Vector3r)*size); memset(_torque[0], 0,sizeof(Vector3r)*size);
+			synced=true;
+		}
+};
+
+#else
 /* Container for Body External Variables (bex), typically forces and torques from interactions.
  * Values should be reset at every iteration by BexResetter.
  * If you want to add your own bex, there are 4 steps:
@@ -22,21 +99,22 @@
 		std::vector<Vector3r> _force;
 		std::vector<Vector3r> _torque;
 		size_t size;
+		inline void ensureSize(body_id_t id){ if(size<=(size_t)id) resize(min((size_t)1.5*(id+100),(size_t)(id+2000)));}
 	public:
 		BexContainer(): size(0){}
-		inline void ensureSize(body_id_t id){ if(size<=(size_t)id) resize(min((size_t)1.5*(id+100),(size_t)(id+2000)));}
-		//! Get writable reference to force acting on body # id
-		inline Vector3r& force(body_id_t id){ ensureSize(id); return _force[id]; }
-		//! Get writable reference to torque acting on body # id
-		inline Vector3r& torque(body_id_t id){ ensureSize(id); return _torque[id]; }
+		const Vector3r& getForce(body_id_t id){ensureSize(id); return _force[id];}
+		void  addForce(body_id_t id,const Vector3r& f){ensureSize(id); _force[id]+=f;}
+		const Vector3r& getTorque(body_id_t id){ensureSize(id); return _torque[id];}
+		void  addTorque(body_id_t id,const Vector3r& t){ensureSize(id); _torque[id]+=t;}
 		//! Set all bex's to zero
 		void reset(){
 			memset(_force[0], 0,sizeof(Vector3r)*size);
 			memset(_torque[0],0,sizeof(Vector3r)*size);
 		}
+		//! No-op for API compatibility with the threaded version
+		void sync(){return;}
 		/*! Resize the container; this happens automatically,
-		 * but you may want to set the size beforehand to avoid resizes as the simulation grows.
-		 */
+		 * but you may want to set the size beforehand to avoid resizes as the simulation grows. */
 		void resize(size_t newSize){
 			_force.resize(newSize);
 			_torque.resize(newSize);
@@ -44,3 +122,6 @@
 			std::cerr<<"[DEBUG] BexContainer: Resized to "<<size<<std::endl;
 		}
 };
+
+
+#endif

Modified: trunk/core/Omega.hpp
===================================================================
--- trunk/core/Omega.hpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/core/Omega.hpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -167,6 +167,7 @@
 		Omega& operator=(const Omega&);
 
 	FRIEND_SINGLETON(Omega);
+	friend class pyOmega;
 };
 
 

Modified: trunk/extra/Brefcom.cpp
===================================================================
--- trunk/extra/Brefcom.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/extra/Brefcom.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -12,7 +12,8 @@
 CREATE_LOGGER(BrefcomGlobalCharacteristics);
 
 void BrefcomGlobalCharacteristics::compute(MetaBody* rb, bool useMaxForce){
-	Shop::Bex::initCache();
+	//Shop::Bex::initCache();
+	rb->bex.sync();
 
 	// 1. reset volumetric strain (cummulative in the next loop)
 	// 2. get maximum force on a body and sum of all forces (for averaging)
@@ -21,7 +22,7 @@
 	BrefcomPhysParams* bpp(YADE_CAST<BrefcomPhysParams*>(b->physicalParameters.get()));
 		bpp->epsVolumetric=0;
 		bpp->numContacts=0;
-		currF=Shop::Bex::force(b->id,rb).Length(); maxF=max(currF,maxF); sumF+=currF;
+		currF=rb->bex.getForce(b->id).Length(); maxF=max(currF,maxF); sumF+=currF;
 	}
 	Real meanF=sumF/rb->bodies->size(); 
 
@@ -124,10 +125,10 @@
 CREATE_LOGGER(BrefcomLaw);
 
 void BrefcomLaw::applyForce(const Vector3r& force, const body_id_t& id1, const body_id_t& id2){
-	Shop::Bex::force(id1,rootBody)+=force;
-	Shop::Bex::force(id2,rootBody)-=force;
-	Shop::Bex::momentum(id1,rootBody)+=(contGeom->contactPoint-contGeom->pos1).Cross(force);
-	Shop::Bex::momentum(id2,rootBody)+=(contGeom->contactPoint-contGeom->pos2).Cross(-force);
+	rootBody->bex.addForce(id1,force);
+	rootBody->bex.addForce(id2,-force);
+	rootBody->bex.addTorque(id1,(contGeom->contactPoint-contGeom->pos1).Cross(force));
+	rootBody->bex.addTorque(id2,(contGeom->contactPoint-contGeom->pos2).Cross(-force));
 }
 
 CREATE_LOGGER(ef2_Spheres_Brefcom_BrefcomLaw);

Modified: trunk/extra/clump/Shop.cpp
===================================================================
--- trunk/extra/clump/Shop.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/extra/clump/Shop.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -39,7 +39,6 @@
 
 #include<yade/pkg-common/Force.hpp>
 #include<yade/pkg-common/Momentum.hpp>
-#include<yade/pkg-dem/GlobalStiffness.hpp>
 /*class InteractingSphere2AABB;
 class InteractingBox2AABB;
 class MetaInteractingGeometry;
@@ -87,18 +86,16 @@
 
 int Shop::Bex::forceIdx=-1;
 int Shop::Bex::momentumIdx=-1;
-int Shop::Bex::globalStiffnessIdx=-1;
 
 void Shop::Bex::initCache(){
 	if(Shop::Bex::forceIdx<0){
 		Shop::Bex::forceIdx=shared_ptr<PhysicalAction>(new Force())->getClassIndex();
 		Shop::Bex::momentumIdx=shared_ptr<PhysicalAction>(new Momentum())->getClassIndex();
-		Shop::Bex::globalStiffnessIdx=shared_ptr<PhysicalAction>(new GlobalStiffness())->getClassIndex();
 	}
 }
 #ifdef BEX_CONTAINER
-	Vector3r& Shop::Bex::force(body_id_t id,MetaBody* rb){ return rb->bex.force(id);}
-	Vector3r& Shop::Bex::momentum(body_id_t id,MetaBody* rb){ return rb->bex.force(id);}
+	const Vector3r& Shop::Bex::force(body_id_t id,MetaBody* rb){  rb->bex.sync();  return rb->bex.getForce(id);}
+	const Vector3r& Shop::Bex::momentum(body_id_t id,MetaBody* rb){ rb->bex.sync(); return rb->bex.getTorque(id);}
 #else
 	#define __BEX_ACCESS(retType,shopBexMember,bexClass,bexIdx,bexAttribute) retType& Shop::Bex::shopBexMember(body_id_t id,MetaBody* mb){ assert(bexIdx>=0); shared_ptr<PhysicalActionContainer> pac=(mb?mb:Omega::instance().getRootBody().get())->physicalActions; /*if((long)pac->size()<=id) throw invalid_argument("No " #shopBexMember " for #"+lexical_cast<string>(id)+" (max="+lexical_cast<string>(((long)pac->size()-1))+")");*/ return static_pointer_cast<bexClass>(pac->find(id,bexIdx))->bexAttribute; }
 	__BEX_ACCESS(Vector3r,force,Force,forceIdx,force);
@@ -110,10 +107,17 @@
  *
  * Shop::Bex::initCache must have been called at some point. */
 void Shop::applyForceAtContactPoint(const Vector3r& force, const Vector3r& contPt, body_id_t id1, const Vector3r& pos1, body_id_t id2, const Vector3r& pos2, MetaBody* rootBody){
+#ifdef BEX_CONTAINER
+	rootBody->bex.addForce(id1,force);
+	rootBody->bex.addForce(id2,-force);
+	rootBody->bex.addTorque(id1,(contPt-pos1).Cross(force));
+	rootBody->bex.addTorque(id2,-(contPt-pos2).Cross(force));
+#else
 	Shop::Bex::force(id1,rootBody)+=force;
 	Shop::Bex::force(id2,rootBody)-=force;
 	Shop::Bex::momentum(id1,rootBody)+=(contPt-pos1).Cross(force);
 	Shop::Bex::momentum(id2,rootBody)-=(contPt-pos2).Cross(force);
+#endif
 }
 
 
@@ -124,7 +128,12 @@
 	Real sumF=0,maxF=0,currF;
 	FOREACH(const shared_ptr<Body>& b, *rb->bodies){
 		if(!b->isDynamic) continue;
-		currF=Shop::Bex::force(b->id,rb).Length(); maxF=max(currF,maxF); sumF+=currF;
+		#ifdef BEX_CONTAINER
+			LOG_FATAL("No implemented with BEX_CONTAINER yet");
+			abort();
+		#else
+			currF=Shop::Bex::force(b->id,rb).Length(); maxF=max(currF,maxF); sumF+=currF;
+		#endif
 	}
 	Real meanF=sumF/rb->bodies->size(); 
 	// get max force on contacts

Modified: trunk/extra/clump/Shop.hpp
===================================================================
--- trunk/extra/clump/Shop.hpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/extra/clump/Shop.hpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -86,12 +86,15 @@
 		 */
 		class Bex{
 			public:
-			static int forceIdx,momentumIdx,globalStiffnessIdx;
+			static int forceIdx,momentumIdx;
 			static void initCache();
-			static Vector3r& force(body_id_t, MetaBody* mb=NULL);
-			static Vector3r& momentum(body_id_t, MetaBody* mb=NULL);
-			static Vector3r& globalStiffness(body_id_t, MetaBody* mb=NULL);
-			static Vector3r& globalRStiffness(body_id_t, MetaBody* mb=NULL);
+			#ifdef BEX_CONTAINER
+				static const Vector3r& force(body_id_t, MetaBody* mb=NULL);
+				static const Vector3r& momentum(body_id_t, MetaBody* mb=NULL);
+			#else
+				static Vector3r& force(body_id_t, MetaBody* mb=NULL);
+				static Vector3r& momentum(body_id_t, MetaBody* mb=NULL);
+			#endif
 		};
 
 		//! Estimate timestep based on P-wave propagation speed

Modified: trunk/extra/usct/UniaxialStrainControlledTest.cpp
===================================================================
--- trunk/extra/usct/UniaxialStrainControlledTest.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/extra/usct/UniaxialStrainControlledTest.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -129,8 +129,9 @@
 void UniaxialStrainer::computeAxialForce(MetaBody* rootBody){
 	sumPosForces=sumNegForces=0;
 	#ifdef BEX_CONTAINER
-		FOREACH(body_id_t id, negIds) sumNegForces+=rootBody->bex.force(id)[axis];
-		FOREACH(body_id_t id, posIds) sumNegForces-=rootBody->bex.force(id)[axis];
+		rootBody->bex.sync();
+		FOREACH(body_id_t id, negIds) sumNegForces+=rootBody->bex.getForce(id)[axis];
+		FOREACH(body_id_t id, posIds) sumNegForces-=rootBody->bex.getForce(id)[axis];
 	#else
 		FOREACH(body_id_t id, negIds) sumNegForces+=Shop::Bex::force(id)[axis];
 		FOREACH(body_id_t id, posIds) sumPosForces-=Shop::Bex::force(id)[axis];

Modified: trunk/gui/py/_utils.cpp
===================================================================
--- trunk/gui/py/_utils.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/gui/py/_utils.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -187,14 +187,19 @@
  * projected onto axis.
  */
 Real sumBexTorques(int mask, python::tuple _axis, python::tuple _axisPt){
+	shared_ptr<MetaBody> rb=Omega::instance().getRootBody();
 	Shop::Bex::initCache();
-	shared_ptr<MetaBody> rb=Omega::instance().getRootBody();
-	Real ret;
+	Real ret=0;
 	Vector3r axis=tuple2vec(_axis), axisPt=tuple2vec(_axisPt);
 	FOREACH(const shared_ptr<Body> b, *rb->bodies){
 		if(!b->maskOk(mask)) continue;
-		const Vector3r& m=Shop::Bex::momentum(b->getId(),rb.get());
-		const Vector3r& f=Shop::Bex::force(b->getId(),rb.get());
+		#ifdef BEX_CONTAINER
+			const Vector3r& m=rb->bex.getTorque(b->getId());
+			const Vector3r& f=rb->bex.getForce(b->getId());
+		#else
+			const Vector3r& m=Shop::Bex::momentum(b->getId(),rb.get());
+			const Vector3r& f=Shop::Bex::force(b->getId(),rb.get());
+		#endif
 		Vector3r r=b->physicalParameters->se3.position-axisPt;
 		ret+=axis.Dot(m+r.Cross(f));
 	}
@@ -213,7 +218,11 @@
 	Vector3r direction=tuple2vec(_direction);
 	FOREACH(const shared_ptr<Body> b, *rb->bodies){
 		if(!b->maskOk(mask)) continue;
-		const Vector3r& f=Shop::Bex::force(b->getId(),rb.get());
+		#ifdef BEX_CONTAINER
+			const Vector3r& f=rb->bex.getForce(b->getId());
+		#else
+			const Vector3r& f=Shop::Bex::force(b->getId(),rb.get());
+		#endif
 		ret+=direction.Dot(f);
 	}
 	return ret;

Modified: trunk/gui/py/yadeControl.cpp
===================================================================
--- trunk/gui/py/yadeControl.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/gui/py/yadeControl.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -387,8 +387,8 @@
 class pyBexContainer{
 	public:
 		pyBexContainer(){}
-		python::tuple force_get(long id){ Vector3r& f=Omega::instance().getRootBody()->bex.force(id); return python::make_tuple(f[0],f[1],f[2]); }
-		python::tuple torque_get(long id){ Vector3r& m=Omega::instance().getRootBody()->bex.torque(id); return python::make_tuple(m[0],m[1],m[2]);}
+		python::tuple force_get(long id){  MetaBody* rb=Omega::instance().getRootBody().get(); rb->bex.sync(); Vector3r f=rb->bex.getForce(id); return python::make_tuple(f[0],f[1],f[2]); }
+		python::tuple torque_get(long id){ MetaBody* rb=Omega::instance().getRootBody().get(); rb->bex.sync(); Vector3r m=rb->bex.getTorque(id); return python::make_tuple(m[0],m[1],m[2]);}
 };
 #endif
 
@@ -459,13 +459,13 @@
 	void loadTmp(string mark){ load(":memory:"+mark);}
 	void tmpToFile(string mark, string filename){
 		// FIXME: memSavedSimulations are private, but I don't want to recompile all yade now; move it to public and uncomment these few lines at some point
-		// if(OMEGA.memSavedSimulations.count(":memory:"+mark)==0) throw runtime_error("No memory-saved simulation named "+mark);
+		if(OMEGA.memSavedSimulations.count(":memory:"+mark)==0) throw runtime_error("No memory-saved simulation named "+mark);
 		iostreams::filtering_ostream out;
 		if(boost::algorithm::ends_with(filename,".bz2")) out.push(iostreams::bzip2_compressor());
 		out.push(iostreams::file_sink(filename));
 		if(!out.good()) throw runtime_error("Error while opening file `"+filename+"' for writing.");
 		LOG_INFO("Saving :memory:"<<mark<<" to "<<filename);
-		//out<<OMEGA.memSavedSimulations[":memory:"+mark];
+		out<<OMEGA.memSavedSimulations[":memory:"+mark];
 	}
 
 

Modified: trunk/pkg/common/Engine/DeusExMachina/GravityEngines.cpp
===================================================================
--- trunk/pkg/common/Engine/DeusExMachina/GravityEngines.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/pkg/common/Engine/DeusExMachina/GravityEngines.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -25,7 +25,7 @@
 		shared_ptr<ParticleParameters> p=YADE_PTR_CAST<ParticleParameters>(b->physicalParameters);
 		if(p!=0) //not everything derives from ParticleParameters; this line was    assert(p); - Janek
 #ifdef BEX_CONTAINER
-			ncb->bex.force(b->getId())+=gravity*p->mass;
+			ncb->bex.addForce(b->getId(),gravity*p->mass);
 #else
 			static_cast<Force*>(ncb->physicalActions->find(b->getId(),cachedForceClassIndex).get())->force+=gravity*p->mass;
 #endif
@@ -39,8 +39,8 @@
 		Real F=accel*YADE_PTR_CAST<ParticleParameters>(b->physicalParameters)->mass;
 		Vector3r toCenter=centralPos-b->physicalParameters->se3.position; toCenter.Normalize();
 #ifdef BEX_CONTAINER
-		rootBody->bex.force(b->getId())+=F*toCenter;
-		if(reciprocal) rootBody->bex.force(centralBody)-=F*toCenter;
+		rootBody->bex.addForce(b->getId(),F*toCenter);
+		if(reciprocal) rootBody->bex.addForce(centralBody,-F*toCenter);
 #else
 		static_cast<Force*>(rootBody->physicalActions->find(b->getId(),cachedForceClassIndex).get())->force+=F*toCenter;
 		if(reciprocal) static_cast<Force*>(rootBody->physicalActions->find(centralBody,cachedForceClassIndex).get())->force-=F*toCenter;
@@ -59,7 +59,7 @@
 		Vector3r closestAxisPoint=(x2-x1) * /* t */ (-(x1-x0).Dot(x2-x1))/((x2-x1).SquaredLength());
 		Vector3r toAxis=closestAxisPoint-x0; toAxis.Normalize();
 #ifdef BEX_CONTAINER
-		rootBody->bex.force(b->getId())+=acceleration*myMass*toAxis;
+		rootBody->bex.addForce(b->getId(),acceleration*myMass*toAxis);
 #else
 		static_pointer_cast<Force>(rootBody->physicalActions->find(b->getId(),cachedForceClassIndex))->force+=acceleration*myMass*toAxis;
 		//if(b->getId()==20){ TRVAR3(toAxis,acceleration*myMass*toAxis,static_pointer_cast<Force>(rootBody->physicalActions->find(b->getId(),cachedForceClassIndex))->force); }

Modified: trunk/pkg/common/Engine/MetaEngine/ConstitutiveLaw.hpp
===================================================================
--- trunk/pkg/common/Engine/MetaEngine/ConstitutiveLaw.hpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/pkg/common/Engine/MetaEngine/ConstitutiveLaw.hpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -23,8 +23,8 @@
 	 * is done only if the derived ConstitutiveLaw says NEEDS_BEX("Force","Momentum"), for example.
 	 */
 #ifdef BEX_CONTAINER
-	inline Vector3r& bodyForce(const body_id_t id, MetaBody* rb) const { return rb->bex.force(id); }
-	inline Vector3r& bodyTorque(const body_id_t id, MetaBody* rb) const { return rb->bex.torque(id);}
+	void addForce (const body_id_t id, const Vector3r& f,MetaBody* rb){rb->bex.addForce (id,f);}
+	void addTorque(const body_id_t id, const Vector3r& t,MetaBody* rb){rb->bex.addTorque(id,t);}
 #else
 	Vector3r& bodyForce(const body_id_t id, MetaBody* rb) const { return static_pointer_cast<Force>(rb->physicalActions->find(id,forceIdx))->force; }
 	Vector3r& bodyTorque(const body_id_t id, MetaBody* rb) const { return static_pointer_cast<Momentum>(rb->physicalActions->find(id,torqueIdx))->momentum;}
@@ -33,9 +33,9 @@
 	/*! Convenience function to apply force and torque from one force at contact point. Not sure if this is the right place for it. */
 	void applyForceAtContactPoint(const Vector3r& force, const Vector3r& contactPoint, const body_id_t id1, const Vector3r& pos1, const body_id_t id2, const Vector3r& pos2, MetaBody* rb){
 		#ifdef BEX_CONTAINER
-			rb->bex.force(id1)+=force; rb->bex.force(id2)-=force;
-			rb->bex.torque(id1)+=(contactPoint-pos1).Cross(force);
-			rb->bex.torque(id2)-=(contactPoint-pos2).Cross(force);
+			rb->bex.addForce(id1,force); rb->bex.addForce(id2,-force);
+			rb->bex.addTorque(id1,(contactPoint-pos1).Cross(force));
+			rb->bex.addTorque(id2,-(contactPoint-pos2).Cross(force));
 		#else
 			bodyForce(id1,rb)+=force; bodyForce(id2,rb)-=force;
 			bodyTorque(id1,rb)+=(contactPoint-pos1).Cross(force);

Modified: trunk/pkg/common/Engine/StandAloneEngine/PhysicalActionContainerInitializer.cpp
===================================================================
--- trunk/pkg/common/Engine/StandAloneEngine/PhysicalActionContainerInitializer.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/pkg/common/Engine/StandAloneEngine/PhysicalActionContainerInitializer.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -32,6 +32,9 @@
 void PhysicalActionContainerInitializer::action(MetaBody* ncb)
 {
 	#ifdef BEX_CONTAINER
+		// this is not necessary, since BexContainer grows upon requests.
+		// But it takes about 10 resizes to get to 2000 bodies (only at the beginning), so you can save a few milliseconds here
+		ncb->bex.resize(ncb->bodies->size());
 		return;
 	#endif
 	list<string> allNames;

Modified: trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp
===================================================================
--- trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/pkg/dem/Engine/DeusExMachina/NewtonsDampedLaw.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -31,17 +31,22 @@
 
 void NewtonsDampedLaw::applyCondition ( MetaBody * ncb )
 {
+	#ifdef BEX_CONTAINER
+		#ifdef YADE_OPENMP
+			ncb->bex.sync();
+		#endif
+	#endif
 	FOREACH(const shared_ptr<Body>& b, *ncb->bodies){
 		if (!b->isDynamic) continue;
 		
 		RigidBodyParameters* rb = YADE_CAST<RigidBodyParameters*>(b->physicalParameters.get());
 		unsigned int id = b->getId();
 		#ifdef BEX_CONTAINER
-			Vector3r& m = ncb->bex.torque(id);
-			Vector3r& f = ncb->bex.force(id);
+			const Vector3r& m=ncb->bex.getTorque(id);
+			const Vector3r& f=ncb->bex.getForce(id);
 		#else
-			Vector3r& m = ( static_cast<Momentum*> ( ncb->physicalActions->find ( id, momentumClassIndex ).get() ) )->momentum;
-			Vector3r& f = ( static_cast<Force*> ( ncb->physicalActions->find ( id, forceClassIndex ).get() ) )->force;
+			const Vector3r& m = ( static_cast<Momentum*> ( ncb->physicalActions->find ( id, momentumClassIndex ).get() ) )->momentum;
+			const Vector3r& f = ( static_cast<Force*> ( ncb->physicalActions->find ( id, forceClassIndex ).get() ) )->force;
 		#endif
 
 		Real dt = Omega::instance().getTimeStep();

Modified: trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.cpp
===================================================================
--- trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -198,7 +198,10 @@
 {
 	//cerr << "TriaxialStressController::applyCondition" << endl;
 	
+	// sync thread storage of BexContainer
+	ncb->bex.sync();
 	
+	
 	shared_ptr<BodyContainer>& bodies = ncb->bodies;
 	
 	

Modified: trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.hpp
===================================================================
--- trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.hpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/pkg/dem/Engine/DeusExMachina/TriaxialStressController.hpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -33,7 +33,7 @@
 		bool firstRun;
 		inline const Vector3r getForce(MetaBody* rb, body_id_t id){
 			#ifdef BEX_CONTAINER
-				return rb->bex.force(id);
+				return rb->bex.getForce(id); // needs sync, which is done at the beginning of applyCondition
 			#else
 				return static_cast<Force*>(rb->physicalActions->find(id,ForceClassIndex).get())->force				
 			#endif

Modified: trunk/pkg/dem/Engine/EngineUnit/Spheres_Viscoelastic_SimpleViscoelasticContactLaw.cpp
===================================================================
--- trunk/pkg/dem/Engine/EngineUnit/Spheres_Viscoelastic_SimpleViscoelasticContactLaw.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/pkg/dem/Engine/EngineUnit/Spheres_Viscoelastic_SimpleViscoelasticContactLaw.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -67,8 +67,8 @@
 	}
 
 	Vector3r f				= phys->normalForce + shearForce;
-	bodyForce (id1,rootBody) -= f;
-	bodyForce (id2,rootBody) += f;
-	bodyTorque(id1,rootBody) -= c1x.Cross(f);
-	bodyTorque(id2,rootBody) += c2x.Cross(f);
+	addForce (id1,-f,rootBody);
+	addForce (id2, f,rootBody);
+	addTorque(id1,-c1x.Cross(f),rootBody);
+	addTorque(id2, c2x.Cross(f),rootBody);
 }

Modified: trunk/pkg/dem/Engine/StandAloneEngine/ElasticContactLaw.cpp
===================================================================
--- trunk/pkg/dem/Engine/StandAloneEngine/ElasticContactLaw.cpp	2009-02-22 13:08:47 UTC (rev 1679)
+++ trunk/pkg/dem/Engine/StandAloneEngine/ElasticContactLaw.cpp	2009-02-22 20:08:45 UTC (rev 1680)
@@ -44,10 +44,15 @@
 		Shop::applyForceAtContactPoint(force,contGeom->contactPoint,i->getId1(),contGeom->pos1,i->getId2(),contGeom->pos2,rb);
 
 		Vector3r bendAbs; Real torsionAbs; contGeom->bendingTorsionAbs(bendAbs,torsionAbs);
-		Shop::Bex::momentum(i->getId1(),rb)+=contGeom->normal*torsionAbs*ktor;
-		Shop::Bex::momentum(i->getId2(),rb)-=contGeom->normal*torsionAbs*ktor;
-		Shop::Bex::momentum(i->getId1(),rb)+=bendAbs*kb;
-		Shop::Bex::momentum(i->getId2(),rb)-=bendAbs*kb;
+		#ifdef BEX_CONTAINER
+			rb->bex.addTorque(i->getId1(), contGeom->normal*torsionAbs*ktor+bendAbs*kb);
+			rb->bex.addTorque(i->getId2(),-contGeom->normal*torsionAbs*ktor-bendAbs*kb);
+		#else
+			Shop::Bex::momentum(i->getId1(),rb)+=contGeom->normal*torsionAbs*ktor;
+			Shop::Bex::momentum(i->getId2(),rb)-=contGeom->normal*torsionAbs*ktor;
+			Shop::Bex::momentum(i->getId1(),rb)+=bendAbs*kb;
+			Shop::Bex::momentum(i->getId2(),rb)-=bendAbs*kb;
+		#endif
 	}
 }
 
@@ -170,10 +175,10 @@
 	
 			Vector3r f				= currentContactPhysics->normalForce + shearForce;
 			#ifdef BEX_CONTAINER
-				ncb->bex.force(id1)-=f;
-				ncb->bex.force(id2)+=f;
-				ncb->bex.torque(id1)-=c1x.Cross(f);
-				ncb->bex.torque(id2)+=c2x.Cross(f);
+				ncb->bex.addForce (id1,-f);
+				ncb->bex.addForce (id2,+f);
+				ncb->bex.addTorque(id1,-c1x.Cross(f));
+				ncb->bex.addTorque(id2, c2x.Cross(f));
 			#else
 				static_cast<Force*>   ( ncb->physicalActions->find( id1 , actionForceIndex).get() )->force    -= f;
 				static_cast<Force*>   ( ncb->physicalActions->find( id2 , actionForceIndex ).get() )->force    += f;