← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-pkg/yade/git-trunk] Rev 3810: Split implementation of ForceContainer in parallel and serial.

 

------------------------------------------------------------
revno: 3810
committer: Anton Gladky <gladky.anton@xxxxxxxxx>
timestamp: Tue 2016-03-22 22:43:26 +0100
message:
  Split implementation of ForceContainer in parallel and serial.
  
  Add ForceContainerSerial.cpp and ForceContainerParallel.cpp,
  ForceContainer.hpp is now common for both of them.
removed:
  core/ForceContainer.cpp
added:
  core/ForceContainerParallel.cpp
  core/ForceContainerSerial.cpp
modified:
  core/ForceContainer.hpp


--
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
=== removed file 'core/ForceContainer.cpp'
--- core/ForceContainer.cpp	2016-03-22 21:43:09 +0000
+++ core/ForceContainer.cpp	1970-01-01 00:00:00 +0000
@@ -1,410 +0,0 @@
-#include <core/ForceContainer.hpp>
-
-#ifdef YADE_OPENMP
-#include <omp.h>
-inline void ForceContainer::ensureSize(Body::id_t id, int threadN) {
-  assert(nThreads>omp_get_thread_num());
-  const Body::id_t idMaxTmp = max(id, _maxId[threadN]);
-  _maxId[threadN] = 0;
-  if (threadN<0) {
-    resizePerm(min((size_t)1.5*(idMaxTmp+100),(size_t)(idMaxTmp+2000)));
-  } else if (sizeOfThreads[threadN]<=(size_t)idMaxTmp) {
-    resize(min((size_t)1.5*(idMaxTmp+100),(size_t)(idMaxTmp+2000)),threadN);
-  }
-}
-
-inline void ForceContainer::ensureSynced() {
-  if(!synced) throw runtime_error("ForceContainer not thread-synchronized; call sync() first!");
-}
-
-ForceContainer::ForceContainer() {
-  nThreads=omp_get_max_threads();
-  for(int i=0; i<nThreads; i++){
-    _forceData.push_back(vvector()); _torqueData.push_back(vvector());
-    _moveData.push_back(vvector());  _rotData.push_back(vvector());
-    sizeOfThreads.push_back(0);
-    _maxId.push_back(0);
-  }
-}
-
-const Vector3r& ForceContainer::getForce(Body::id_t id) {
-  ensureSynced();
-  return ((size_t)id<size)?_force[id]:_zero;
-}
-
-void ForceContainer::addForce(Body::id_t id, const Vector3r& f){
-  ensureSize(id,omp_get_thread_num());
-  synced=false;
-  _forceData[omp_get_thread_num()][id]+=f;
-}
-
-const Vector3r& ForceContainer::getTorque(Body::id_t id) {
-  ensureSynced();
-  return ((size_t)id<size)?_torque[id]:_zero;
-}
-
-void ForceContainer::addTorque(Body::id_t id, const Vector3r& t) {
-  ensureSize(id,omp_get_thread_num());
-  synced=false;
-  _torqueData[omp_get_thread_num()][id]+=t;
-}
-
-const Vector3r& ForceContainer::getMove(Body::id_t id) {
-  ensureSynced();
-  return ((size_t)id<size)?_move[id]:_zero;
-}
-
-void ForceContainer::addMove(Body::id_t id, const Vector3r& m) {
-  ensureSize(id,omp_get_thread_num());
-  synced=false;
-  moveRotUsed=true;
-  _moveData[omp_get_thread_num()][id]+=m;
-}
-
-const Vector3r& ForceContainer::getRot(Body::id_t id) {
-  ensureSynced();
-  return ((size_t)id<size)?_rot[id]:_zero;
-}
-
-void ForceContainer::addRot(Body::id_t id, const Vector3r& r) {
-  ensureSize(id,omp_get_thread_num());
-  synced=false;
-  moveRotUsed=true;
-  _rotData[omp_get_thread_num()][id]+=r;
-}
-
-void ForceContainer::addMaxId(Body::id_t id) {
-  _maxId[omp_get_thread_num()]=id;
-}
-
-void ForceContainer::setPermForce(Body::id_t id, const Vector3r& f) {
-  ensureSize(id,-1);
-  synced=false;
-  _permForce[id]=f;
-  permForceUsed=true;
-}
-
-void ForceContainer::setPermTorque(Body::id_t id, const Vector3r& t) {
-  ensureSize(id,-1);
-  synced=false;
-  _permTorque[id]=t;
-  permForceUsed=true;
-}
-
-const Vector3r& ForceContainer::getPermForce(Body::id_t id) {
-  ensureSynced();
-  return ((size_t)id<size)?_permForce[id]:_zero;
-}
-
-const Vector3r& ForceContainer::getPermTorque(Body::id_t id) {
-  ensureSynced();
-  return ((size_t)id<size)?_permTorque[id]:_zero;
-}
-
-const Vector3r& ForceContainer::getForceUnsynced(Body::id_t id) {
-  assert ((size_t)id<size);
-  return _force[id];
-}
-
-const Vector3r& ForceContainer::getTorqueUnsynced(Body::id_t id) {
-  assert ((size_t)id<size);
-  return _torque[id];
-}
-
-void ForceContainer::addForceUnsynced(Body::id_t id, const Vector3r& f) {
-  assert ((size_t)id<size);
-  _force[id]+=f;
-}
-
-void ForceContainer::addTorqueUnsynced(Body::id_t id, const Vector3r& m) {
-  assert ((size_t)id<size);
-  _torque[id]+=m;
-}
-
-Vector3r ForceContainer::getForceSingle(Body::id_t id) {
-  Vector3r ret(Vector3r::Zero());
-  for(int t=0; t<nThreads; t++) {
-    ret+=((size_t)id<sizeOfThreads[t])?_forceData [t][id]:_zero;
-  }
-  if (permForceUsed) ret+=_permForce[id];
-  return ret;
-}
-
-Vector3r ForceContainer::getTorqueSingle(Body::id_t id) {
-  Vector3r ret(Vector3r::Zero());
-  for(int t=0; t<nThreads; t++) {
-    ret+=((size_t)id<sizeOfThreads[t])?_torqueData[t][id]:_zero;
-  }
-  if (permForceUsed) ret+=_permTorque[id];
-  return ret;
-}
-
-Vector3r ForceContainer::getMoveSingle(Body::id_t id) {
-  Vector3r ret(Vector3r::Zero());
-  for(int t=0; t<nThreads; t++) {
-    ret+=((size_t)id<sizeOfThreads[t])?_moveData[t][id]:_zero;
-  }
-  return ret;
-}
-
-Vector3r ForceContainer::getRotSingle(Body::id_t id) {
-  Vector3r ret(Vector3r::Zero());
-  for(int t=0; t<nThreads; t++) {
-    ret+=((size_t)id<sizeOfThreads[t])?_rotData[t][id]:_zero;
-  }
-  return ret;
-}
-
-void ForceContainer::syncSizesOfContainers() {
-  if (syncedSizes) return;
-  //check whether all containers have equal length, and if not resize it
-  for(int i=0; i<nThreads; i++){
-    if (sizeOfThreads[i]<size) resize(size,i);
-  }
-  _force.resize(size,Vector3r::Zero());
-  _torque.resize(size,Vector3r::Zero());
-  _permForce.resize(size,Vector3r::Zero());
-  _permTorque.resize(size,Vector3r::Zero());
-  _move.resize(size,Vector3r::Zero());
-  _rot.resize(size,Vector3r::Zero());
-  syncedSizes=true;
-}
-
-void ForceContainer::sync(){
-  for(int i=0; i<nThreads; i++){
-    if (_maxId[i] > 0) { synced = false;}
-  }
-  if(synced) return;
-  boost::mutex::scoped_lock lock(globalMutex);
-  if(synced) return; // if synced meanwhile
-  
-  for(int i=0; i<nThreads; i++){
-    if (_maxId[i] > 0) { ensureSize(_maxId[i],i);}
-  }
-  
-  syncSizesOfContainers();
-
-  for(long id=0; id<(long)size; id++){
-    Vector3r sumF(Vector3r::Zero()), sumT(Vector3r::Zero());
-    for(int thread=0; thread<nThreads; thread++){ sumF+=_forceData[thread][id]; sumT+=_torqueData[thread][id];}
-    _force[id]=sumF; _torque[id]=sumT;
-    if (permForceUsed) {_force[id]+=_permForce[id]; _torque[id]+=_permTorque[id];}
-  }
-  if(moveRotUsed){
-    for(long id=0; id<(long)size; id++){
-      Vector3r sumM(Vector3r::Zero()), sumR(Vector3r::Zero());
-      for(int thread=0; thread<nThreads; thread++){ sumM+=_moveData[thread][id]; sumR+=_rotData[thread][id];}
-      _move[id]=sumM; _rot[id]=sumR;
-    }
-  }
-  synced=true; syncCount++;
-}
-
-void ForceContainer::resize(size_t newSize, int threadN) {
-  _forceData [threadN].resize(newSize,Vector3r::Zero());
-  _torqueData[threadN].resize(newSize,Vector3r::Zero());
-  _moveData[threadN].resize(newSize,Vector3r::Zero());
-  _rotData[threadN].resize(newSize,Vector3r::Zero());
-  sizeOfThreads[threadN] = newSize;
-  if (size<newSize) size=newSize;
-  syncedSizes=false;
-}
-
-void ForceContainer::resizePerm(size_t newSize) {
-  _permForce.resize(newSize,Vector3r::Zero());
-  _permTorque.resize(newSize,Vector3r::Zero());
-  if (size<newSize) size=newSize;
-  syncedSizes=false;
-}
-
-void ForceContainer::reset(long iter, bool resetAll) {
-  syncSizesOfContainers();
-  for(int thread=0; thread<nThreads; thread++){
-    memset(&_forceData [thread][0],0,sizeof(Vector3r)*sizeOfThreads[thread]);
-    memset(&_torqueData[thread][0],0,sizeof(Vector3r)*sizeOfThreads[thread]);
-    if(moveRotUsed){
-      memset(&_moveData  [thread][0],0,sizeof(Vector3r)*sizeOfThreads[thread]);
-      memset(&_rotData   [thread][0],0,sizeof(Vector3r)*sizeOfThreads[thread]);
-    }
-  }
-  memset(&_force [0], 0,sizeof(Vector3r)*size);
-  memset(&_torque[0], 0,sizeof(Vector3r)*size);
-  if(moveRotUsed){
-    memset(&_move  [0], 0,sizeof(Vector3r)*size);
-    memset(&_rot   [0], 0,sizeof(Vector3r)*size);
-  }
-  if (resetAll){
-    memset(&_permForce [0], 0,sizeof(Vector3r)*size);
-    memset(&_permTorque[0], 0,sizeof(Vector3r)*size);
-    permForceUsed = false;
-  }
-  if (!permForceUsed) synced=true; else synced=false;
-  moveRotUsed=false;
-  lastReset=iter;
-}
-
-const int& ForceContainer::getNumAllocatedThreads() {
-  return nThreads;
-}
-
-const bool& ForceContainer::getMoveRotUsed() {
-  return moveRotUsed;
-}
-
-const bool& ForceContainer::getPermForceUsed() {
-  return permForceUsed;
-}
-
-#else
-void ForceContainer::ensureSize(Body::id_t id) {
-  const Body::id_t idMaxTmp = max(id, _maxId);
-  _maxId = 0;
-  if(size<=(size_t)idMaxTmp) resize(min((size_t)1.5*(idMaxTmp+100),(size_t)(idMaxTmp+2000)));
-}
-
-const Vector3r& ForceContainer::getForceUnsynced (Body::id_t id) {
-  return getForce(id);
-}
-
-const Vector3r& ForceContainer::getTorqueUnsynced(Body::id_t id) {
-  return getForce(id);
-}
-
-const Vector3r& ForceContainer::getForce(Body::id_t id) {
-  ensureSize(id);
-  return _force[id];
-}
-
-void ForceContainer::addForce(Body::id_t id,const Vector3r& f) {
-  ensureSize(id);
-  _force[id]+=f;
-}
-
-const Vector3r& ForceContainer::getTorque(Body::id_t id) {
-  ensureSize(id);
-  return _torque[id];
-}
-
-void ForceContainer::addTorque(Body::id_t id,const Vector3r& t) {
-  ensureSize(id);
-  _torque[id]+=t;
-}
-
-const Vector3r& ForceContainer::getMove(Body::id_t id) {
-  ensureSize(id);
-  return _move[id];
-}
-
-void ForceContainer::addMove(Body::id_t id,const Vector3r& f) {
-  ensureSize(id);
-  moveRotUsed=true;
-  _move[id]+=f;
-}
-
-const Vector3r& ForceContainer::getRot(Body::id_t id) {
-  ensureSize(id);
-  return _rot[id];
-}
-
-void ForceContainer::addRot(Body::id_t id,const Vector3r& f) {
-  ensureSize(id);
-  moveRotUsed=true;
-  _rot[id]+=f;
-}
-
-void ForceContainer::setPermForce(Body::id_t id, const Vector3r& f) {
-  ensureSize(id);
-  _permForce[id]=f;
-  permForceUsed=true;
-}
-
-void ForceContainer::setPermTorque(Body::id_t id, const Vector3r& t) {
-  ensureSize(id);
-  _permTorque[id]=t;
-  permForceUsed=true;
-}
-
-void ForceContainer::addMaxId(Body::id_t id) {
-  _maxId=id;
-}
-
-const Vector3r& ForceContainer::getPermForce(Body::id_t id) {
-  ensureSize(id);
-  return _permForce[id];
-}
-
-const Vector3r& ForceContainer::getPermTorque(Body::id_t id) {
-  ensureSize(id);
-  return _permTorque[id];
-}
-
-const Vector3r ForceContainer::getForceSingle (Body::id_t id) { 
-  ensureSize(id); 
-  if (permForceUsed) {
-    return _force [id] + _permForce[id];
-  } else {
-    return _force [id];
-  }
-}
-const Vector3r ForceContainer::getTorqueSingle(Body::id_t id) { 
-  ensureSize(id); 
-  if (permForceUsed) {
-    return _torque[id] + _permTorque[id];
-  } else {
-    return _torque[id];
-  }
-}
-const Vector3r& ForceContainer::getMoveSingle(Body::id_t id) {
-  ensureSize(id);
-  return _move [id];
-}
-
-const Vector3r& ForceContainer::getRotSingle(Body::id_t id) {
-  ensureSize(id);
-  return _rot[id];
-}
-
-void ForceContainer::reset(long iter, bool resetAll) {
-  memset(&_force [0],0,sizeof(Vector3r)*size);
-  memset(&_torque[0],0,sizeof(Vector3r)*size);
-  if(moveRotUsed){
-    memset(&_move  [0],0,sizeof(Vector3r)*size);
-    memset(&_rot   [0],0,sizeof(Vector3r)*size);
-    moveRotUsed=false;
-  }
-  if (resetAll){
-    memset(&_permForce [0], 0,sizeof(Vector3r)*size);
-    memset(&_permTorque[0], 0,sizeof(Vector3r)*size);
-    permForceUsed = false;
-  }
-  lastReset=iter;
-}
-
-void ForceContainer::sync() {
-  if (_maxId>0) {
-    ensureSize(_maxId);
-    _maxId=0;
-  }
-  if (permForceUsed) {
-    for(long id=0; id<(long)size; id++) {
-      _force[id]+=_permForce[id];
-      _torque[id]+=_permTorque[id];
-    }
-  }
-  return;
-}
-
-void ForceContainer::resize(size_t newSize) {
-  _force.resize(newSize,Vector3r::Zero());
-  _torque.resize(newSize,Vector3r::Zero());
-  _permForce.resize(newSize,Vector3r::Zero());
-  _permTorque.resize(newSize,Vector3r::Zero());
-  _move.resize(newSize,Vector3r::Zero());
-  _rot.resize(newSize,Vector3r::Zero());
-  size=newSize;
-}
-
-const int ForceContainer::getNumAllocatedThreads() const {return 1;}
-const bool& ForceContainer::getMoveRotUsed() const {return moveRotUsed;}
-const bool& ForceContainer::getPermForceUsed() const {return permForceUsed;}
-#endif

=== modified file 'core/ForceContainer.hpp'
--- core/ForceContainer.hpp	2016-03-22 21:43:09 +0000
+++ core/ForceContainer.hpp	2016-03-22 21:43:26 +0000
@@ -1,17 +1,18 @@
 // 2009 © Václav Šmilauer <eudoxos@xxxxxxxx>
 #pragma once
 
-#include<lib/base/Math.hpp>
-#include<core/Body.hpp>
+#include <lib/base/Math.hpp>
+#include <core/Body.hpp>
 
-#include<boost/static_assert.hpp>
+#include <boost/static_assert.hpp>
 // make sure that (void*)&vec[0]==(void*)&vec
 BOOST_STATIC_ASSERT(sizeof(Vector3r)==3*sizeof(Real));
 
 
 #ifdef YADE_OPENMP
+#include <omp.h>
+#endif
 
-#include<omp.h>
 /*! Container for Body External Variables (forces), typically forces and torques from interactions.
  * Values should be reset at every iteration by calling ForceContainer::reset();
  * If you want to add your own force type, you need to:
@@ -41,16 +42,22 @@
  */
 
 //! This is the parallel flavor of ForceContainer
-class ForceContainer{
+class ForceContainer {
 	private:
 		typedef std::vector<Vector3r> vvector;
+#ifdef YADE_OPENMP
 		std::vector<vvector> _forceData;
 		std::vector<vvector> _torqueData;
 		std::vector<vvector> _moveData;
 		std::vector<vvector> _rotData;
-		std::vector<Body::id_t>  _maxId;
+		std::vector<Body::id_t> _maxId;
+		std::vector<size_t> sizeOfThreads;
+		void ensureSize(Body::id_t id, int threadN);
+#else
+		void ensureSize(Body::id_t id);
+		Body::id_t _maxId=0;
+#endif
 		vvector _force, _torque, _move, _rot, _permForce, _permTorque;
-		std::vector<size_t> sizeOfThreads;
 		size_t size = 0;
 		bool syncedSizes = true;
 		int nThreads;
@@ -58,9 +65,9 @@
 		bool moveRotUsed = false;
 		bool permForceUsed = false;
 		boost::mutex globalMutex;
-		Vector3r _zero = Vector3r::Zero();
+		const Vector3r _zero = Vector3r::Zero();
 
-		void ensureSize(Body::id_t id, int threadN);
+		
 		void ensureSynced();
 		
 		// dummy function to avoid template resolution failure
@@ -96,82 +103,29 @@
 		/* To be benchmarked: sum thread data in getForce/getTorque upon request for each body individually instead of by the sync() function globally */
 		// this function is used from python so that running simulation is not slowed down by sync'ing on occasions
 		// since Vector3r writes are not atomic, it might (rarely) return wrong value, if the computation is running meanwhile
-		Vector3r getForceSingle (Body::id_t id);
-		Vector3r getTorqueSingle(Body::id_t id);
-		Vector3r getMoveSingle  (Body::id_t id);
-		Vector3r getRotSingle   (Body::id_t id);
-		
+		const Vector3r getForceSingle (Body::id_t id);
+		const Vector3r getTorqueSingle(Body::id_t id);
+		const Vector3r getMoveSingle  (Body::id_t id);
+		const Vector3r getRotSingle   (Body::id_t id);
+
+#ifdef YADE_OPENMP
 		void syncSizesOfContainers();
+		void resize(size_t newSize, int threadN);
+#else
+		void resize(size_t newSize);
+#endif
 		/* Sum contributions from all threads, save to _force&_torque.
 		 * Locks globalMutex, since one thread modifies common data (_force&_torque).
 		 * Must be called before get* methods are used. Exception is thrown otherwise, since data are not consistent. */
 		void sync();
-		void resize(size_t newSize, int threadN);
+
 		void resizePerm(size_t newSize);
 		/*! Reset all resetable data, also reset summary forces/torques and mark the container clean.
 		If resetAll, reset also user defined forces and torques*/
 		// perhaps should be private and friend Scene or whatever the only caller should be
 		void reset(long iter, bool resetAll=false);
 		//! say for how many threads we have allocated space
-		const int& getNumAllocatedThreads();
-		const bool& getMoveRotUsed();
-		const bool& getPermForceUsed();
-};
-
-#else
-//! This is the non-parallel flavor of ForceContainer
-class ForceContainer {
-	private:
-		std::vector<Vector3r> _force;
-		std::vector<Vector3r> _torque;
-		std::vector<Vector3r> _move;
-		std::vector<Vector3r> _rot;
-		std::vector<Vector3r> _permForce;
-		std::vector<Vector3r> _permTorque;
-		Body::id_t _maxId=0;
-		size_t size=0;
-		bool moveRotUsed = false;
-		bool permForceUsed = false;
-		void ensureSize(Body::id_t id);
-		
-		const Vector3r& getForceUnsynced (Body::id_t id);
-		const Vector3r& getTorqueUnsynced(Body::id_t id);
-		
-		// dummy function to avoid template resolution failure
-		friend class boost::serialization::access; template<class ArchiveT> void serialize(ArchiveT & ar, unsigned int version){}
-	public:
-		unsigned long syncCount = 0;
-		long lastReset=0;
-		ForceContainer() {}
-		const Vector3r& getForce(Body::id_t id);
-		void  addForce(Body::id_t id,const Vector3r& f);
-		const Vector3r& getTorque(Body::id_t id);
-		void  addTorque(Body::id_t id,const Vector3r& t);
-		const Vector3r& getMove(Body::id_t id);
-		void  addMove(Body::id_t id,const Vector3r& f);
-		const Vector3r& getRot(Body::id_t id);
-		void  addRot(Body::id_t id,const Vector3r& f);
-		void  setPermForce(Body::id_t id, const Vector3r& f);
-		void setPermTorque(Body::id_t id, const Vector3r& t);
-		void  addMaxId(Body::id_t id);
-		const Vector3r& getPermForce(Body::id_t id);
-		const Vector3r& getPermTorque(Body::id_t id);
-		// single getters do the same as globally synced ones in the non-parallel flavor
-		const Vector3r getForceSingle (Body::id_t id);
-		const Vector3r getTorqueSingle(Body::id_t id);
-		const Vector3r& getMoveSingle  (Body::id_t id);
-		const Vector3r& getRotSingle   (Body::id_t id);
-
-		//! Set all forces to zero
-		void reset(long iter, bool resetAll=false);
-		void sync();
-		// interaction in which the container was last reset; used by NewtonIntegrator to detect whether ForceResetter was not forgotten
-		/*! Resize the container; this happens automatically,
-		 * but you may want to set the size beforehand to avoid resizes as the simulation grows. */
-		void resize(size_t newSize);
 		const int getNumAllocatedThreads() const;
-		const bool& getMoveRotUsed() const;
-		const bool& getPermForceUsed() const;
+		const bool getMoveRotUsed() const;
+		const bool getPermForceUsed() const;
 };
-
-#endif

=== added file 'core/ForceContainerParallel.cpp'
--- core/ForceContainerParallel.cpp	1970-01-01 00:00:00 +0000
+++ core/ForceContainerParallel.cpp	2016-03-22 21:43:26 +0000
@@ -0,0 +1,251 @@
+#include <core/ForceContainer.hpp>
+
+void ForceContainer::ensureSynced() {
+  if(!synced) throw runtime_error("ForceContainer not thread-synchronized; call sync() first!");
+}
+
+void ForceContainer::addForceUnsynced(Body::id_t id, const Vector3r& f) {
+  assert ((size_t)id<size);
+  _force[id]+=f;
+}
+
+void ForceContainer::addTorqueUnsynced(Body::id_t id, const Vector3r& m) {
+  assert ((size_t)id<size);
+  _torque[id]+=m;
+}
+
+void ForceContainer::resizePerm(size_t newSize) {
+  _permForce.resize(newSize,Vector3r::Zero());
+  _permTorque.resize(newSize,Vector3r::Zero());
+  if (size<newSize) size=newSize;
+  syncedSizes=false;
+}
+
+#ifdef YADE_OPENMP
+#include <omp.h>
+void ForceContainer::ensureSize(Body::id_t id, int threadN) {
+  assert(nThreads>omp_get_thread_num());
+  const Body::id_t idMaxTmp = max(id, _maxId[threadN]);
+  _maxId[threadN] = 0;
+  if (threadN<0) {
+    resizePerm(min((size_t)1.5*(idMaxTmp+100),(size_t)(idMaxTmp+2000)));
+  } else if (sizeOfThreads[threadN]<=(size_t)idMaxTmp) {
+    resize(min((size_t)1.5*(idMaxTmp+100),(size_t)(idMaxTmp+2000)),threadN);
+  }
+}
+
+ForceContainer::ForceContainer() {
+  nThreads=omp_get_max_threads();
+  for(int i=0; i<nThreads; i++){
+    _forceData.push_back(vvector());
+    _torqueData.push_back(vvector());
+    _moveData.push_back(vvector());
+    _rotData.push_back(vvector());
+    sizeOfThreads.push_back(0);
+    _maxId.push_back(0);
+  }
+}
+
+const Vector3r& ForceContainer::getForce(Body::id_t id) {
+  ensureSynced();
+  return ((size_t)id<size)?_force[id]:_zero;
+}
+
+void ForceContainer::addForce(Body::id_t id, const Vector3r& f){
+  ensureSize(id,omp_get_thread_num());
+  synced=false;
+  _forceData[omp_get_thread_num()][id]+=f;
+}
+
+const Vector3r& ForceContainer::getTorque(Body::id_t id) {
+  ensureSynced();
+  return ((size_t)id<size)?_torque[id]:_zero;
+}
+
+void ForceContainer::addTorque(Body::id_t id, const Vector3r& t) {
+  ensureSize(id,omp_get_thread_num());
+  synced=false;
+  _torqueData[omp_get_thread_num()][id]+=t;
+}
+
+const Vector3r& ForceContainer::getMove(Body::id_t id) {
+  ensureSynced();
+  return ((size_t)id<size)?_move[id]:_zero;
+}
+
+void ForceContainer::addMove(Body::id_t id, const Vector3r& m) {
+  ensureSize(id,omp_get_thread_num());
+  synced=false;
+  moveRotUsed=true;
+  _moveData[omp_get_thread_num()][id]+=m;
+}
+
+const Vector3r& ForceContainer::getRot(Body::id_t id) {
+  ensureSynced();
+  return ((size_t)id<size)?_rot[id]:_zero;
+}
+
+void ForceContainer::addRot(Body::id_t id, const Vector3r& r) {
+  ensureSize(id,omp_get_thread_num());
+  synced=false;
+  moveRotUsed=true;
+  _rotData[omp_get_thread_num()][id]+=r;
+}
+
+void ForceContainer::addMaxId(Body::id_t id) {
+  _maxId[omp_get_thread_num()]=id;
+}
+
+void ForceContainer::setPermForce(Body::id_t id, const Vector3r& f) {
+  ensureSize(id,-1);
+  synced=false;
+  _permForce[id]=f;
+  permForceUsed=true;
+}
+
+void ForceContainer::setPermTorque(Body::id_t id, const Vector3r& t) {
+  ensureSize(id,-1);
+  synced=false;
+  _permTorque[id]=t;
+  permForceUsed=true;
+}
+
+const Vector3r& ForceContainer::getPermForce(Body::id_t id) {
+  ensureSynced();
+  return ((size_t)id<size)?_permForce[id]:_zero;
+}
+
+const Vector3r& ForceContainer::getPermTorque(Body::id_t id) {
+  ensureSynced();
+  return ((size_t)id<size)?_permTorque[id]:_zero;
+}
+
+const Vector3r& ForceContainer::getForceUnsynced(Body::id_t id) {
+  assert ((size_t)id<size);
+  return _force[id];
+}
+
+const Vector3r& ForceContainer::getTorqueUnsynced(Body::id_t id) {
+  assert ((size_t)id<size);
+  return _torque[id];
+}
+
+const Vector3r ForceContainer::getForceSingle(Body::id_t id) {
+  Vector3r ret(Vector3r::Zero());
+  for(int t=0; t<nThreads; t++) {
+    ret+=((size_t)id<sizeOfThreads[t])?_forceData [t][id]:_zero;
+  }
+  if (permForceUsed) ret+=_permForce[id];
+  return ret;
+}
+
+const Vector3r ForceContainer::getTorqueSingle(Body::id_t id) {
+  Vector3r ret(Vector3r::Zero());
+  for(int t=0; t<nThreads; t++) {
+    ret+=((size_t)id<sizeOfThreads[t])?_torqueData[t][id]:_zero;
+  }
+  if (permForceUsed) ret+=_permTorque[id];
+  return ret;
+}
+
+const Vector3r ForceContainer::getMoveSingle(Body::id_t id) {
+  Vector3r ret(Vector3r::Zero());
+  for(int t=0; t<nThreads; t++) {
+    ret+=((size_t)id<sizeOfThreads[t])?_moveData[t][id]:_zero;
+  }
+  return ret;
+}
+
+const Vector3r ForceContainer::getRotSingle(Body::id_t id) {
+  Vector3r ret(Vector3r::Zero());
+  for(int t=0; t<nThreads; t++) {
+    ret+=((size_t)id<sizeOfThreads[t])?_rotData[t][id]:_zero;
+  }
+  return ret;
+}
+
+void ForceContainer::sync(){
+  for(int i=0; i<nThreads; i++){
+    if (_maxId[i] > 0) { synced = false;}
+  }
+  if(synced) return;
+  boost::mutex::scoped_lock lock(globalMutex);
+  if(synced) return; // if synced meanwhile
+  
+  for(int i=0; i<nThreads; i++){
+    if (_maxId[i] > 0) { ensureSize(_maxId[i],i);}
+  }
+  
+  syncSizesOfContainers();
+
+  for(long id=0; id<(long)size; id++){
+    Vector3r sumF(Vector3r::Zero()), sumT(Vector3r::Zero());
+    for(int thread=0; thread<nThreads; thread++){ sumF+=_forceData[thread][id]; sumT+=_torqueData[thread][id];}
+    _force[id]=sumF; _torque[id]=sumT;
+    if (permForceUsed) {_force[id]+=_permForce[id]; _torque[id]+=_permTorque[id];}
+  }
+  if(moveRotUsed){
+    for(long id=0; id<(long)size; id++){
+      Vector3r sumM(Vector3r::Zero()), sumR(Vector3r::Zero());
+      for(int thread=0; thread<nThreads; thread++){ sumM+=_moveData[thread][id]; sumR+=_rotData[thread][id];}
+      _move[id]=sumM; _rot[id]=sumR;
+    }
+  }
+  synced=true; syncCount++;
+}
+
+void ForceContainer::reset(long iter, bool resetAll) {
+  syncSizesOfContainers();
+  for(int thread=0; thread<nThreads; thread++){
+    memset(&_forceData [thread][0],0,sizeof(Vector3r)*sizeOfThreads[thread]);
+    memset(&_torqueData[thread][0],0,sizeof(Vector3r)*sizeOfThreads[thread]);
+    if(moveRotUsed){
+      memset(&_moveData  [thread][0],0,sizeof(Vector3r)*sizeOfThreads[thread]);
+      memset(&_rotData   [thread][0],0,sizeof(Vector3r)*sizeOfThreads[thread]);
+    }
+  }
+  memset(&_force [0], 0,sizeof(Vector3r)*size);
+  memset(&_torque[0], 0,sizeof(Vector3r)*size);
+  if(moveRotUsed){
+    memset(&_move  [0], 0,sizeof(Vector3r)*size);
+    memset(&_rot   [0], 0,sizeof(Vector3r)*size);
+  }
+  if (resetAll){
+    memset(&_permForce [0], 0,sizeof(Vector3r)*size);
+    memset(&_permTorque[0], 0,sizeof(Vector3r)*size);
+    permForceUsed = false;
+  }
+  if (!permForceUsed) synced=true; else synced=false;
+  moveRotUsed=false;
+  lastReset=iter;
+}
+
+void ForceContainer::resize(size_t newSize, int threadN) {
+  _forceData [threadN].resize(newSize,Vector3r::Zero());
+  _torqueData[threadN].resize(newSize,Vector3r::Zero());
+  _moveData[threadN].resize(newSize,Vector3r::Zero());
+  _rotData[threadN].resize(newSize,Vector3r::Zero());
+  sizeOfThreads[threadN] = newSize;
+  if (size<newSize) size=newSize;
+  syncedSizes=false;
+}
+
+const int ForceContainer::getNumAllocatedThreads() const {return nThreads;}
+const bool ForceContainer::getMoveRotUsed() const {return moveRotUsed;}
+const bool ForceContainer::getPermForceUsed() const {return permForceUsed;}
+
+void ForceContainer::syncSizesOfContainers() {
+  if (syncedSizes) return;
+  //check whether all containers have equal length, and if not resize it
+  for(int i=0; i<nThreads; i++){
+    if (sizeOfThreads[i]<size) resize(size,i);
+  }
+  _force.resize(size,Vector3r::Zero());
+  _torque.resize(size,Vector3r::Zero());
+  _permForce.resize(size,Vector3r::Zero());
+  _permTorque.resize(size,Vector3r::Zero());
+  _move.resize(size,Vector3r::Zero());
+  _rot.resize(size,Vector3r::Zero());
+  syncedSizes=true;
+}
+#endif

=== added file 'core/ForceContainerSerial.cpp'
--- core/ForceContainerSerial.cpp	1970-01-01 00:00:00 +0000
+++ core/ForceContainerSerial.cpp	2016-03-22 21:43:26 +0000
@@ -0,0 +1,157 @@
+#ifndef YADE_OPENMP
+#include <core/ForceContainer.hpp>
+ForceContainer::ForceContainer() {};
+void ForceContainer::ensureSize(Body::id_t id) {
+  const Body::id_t idMaxTmp = max(id, _maxId);
+  _maxId = 0;
+  if(size<=(size_t)idMaxTmp) {
+    resize(min((size_t)1.5*(idMaxTmp+100),(size_t)(idMaxTmp+2000)));
+  };
+}
+
+const Vector3r& ForceContainer::getForce(Body::id_t id) {
+  ensureSize(id);
+  return _force[id];
+}
+
+void ForceContainer::addForce(Body::id_t id,const Vector3r& f) {
+  ensureSize(id);
+  _force[id]+=f;
+}
+
+const Vector3r& ForceContainer::getTorque(Body::id_t id) {
+  ensureSize(id);
+  return _torque[id];
+}
+
+void ForceContainer::addTorque(Body::id_t id,const Vector3r& t) {
+  ensureSize(id);
+  _torque[id]+=t;
+}
+
+const Vector3r& ForceContainer::getMove(Body::id_t id) {
+  ensureSize(id);
+  return _move[id];
+}
+
+void ForceContainer::addMove(Body::id_t id,const Vector3r& f) {
+  ensureSize(id);
+  moveRotUsed=true;
+  _move[id]+=f;
+}
+
+const Vector3r& ForceContainer::getRot(Body::id_t id) {
+  ensureSize(id);
+  return _rot[id];
+}
+
+void ForceContainer::addRot(Body::id_t id,const Vector3r& f) {
+  ensureSize(id);
+  moveRotUsed=true;
+  _rot[id]+=f;
+}
+
+void ForceContainer::addMaxId(Body::id_t id) {
+  _maxId=id;
+}
+
+void ForceContainer::setPermForce(Body::id_t id, const Vector3r& f) {
+  ensureSize(id);
+  _permForce[id]=f;
+  permForceUsed=true;
+}
+
+void ForceContainer::setPermTorque(Body::id_t id, const Vector3r& t) {
+  ensureSize(id);
+  _permTorque[id]=t;
+  permForceUsed=true;
+}
+
+const Vector3r& ForceContainer::getPermForce(Body::id_t id) {
+  ensureSize(id);
+  return _permForce[id];
+}
+
+const Vector3r& ForceContainer::getPermTorque(Body::id_t id) {
+  ensureSize(id);
+  return _permTorque[id];
+}
+
+const Vector3r& ForceContainer::getForceUnsynced (Body::id_t id) {
+  return getForce(id);
+}
+
+const Vector3r& ForceContainer::getTorqueUnsynced(Body::id_t id) {
+  return getForce(id);
+}
+
+const Vector3r ForceContainer::getForceSingle (Body::id_t id) { 
+  ensureSize(id); 
+  if (permForceUsed) {
+    return _force [id] + _permForce[id];
+  } else {
+    return _force [id];
+  }
+}
+const Vector3r ForceContainer::getTorqueSingle(Body::id_t id) { 
+  ensureSize(id); 
+  if (permForceUsed) {
+    return _torque[id] + _permTorque[id];
+  } else {
+    return _torque[id];
+  }
+}
+const Vector3r ForceContainer::getMoveSingle(Body::id_t id) {
+  ensureSize(id);
+  return _move [id];
+}
+
+const Vector3r ForceContainer::getRotSingle(Body::id_t id) {
+  ensureSize(id);
+  return _rot[id];
+}
+
+void ForceContainer::sync() {
+  if (_maxId>0) {
+    ensureSize(_maxId);
+    _maxId=0;
+  }
+  if (permForceUsed) {
+    for(long id=0; id<(long)size; id++) {
+      _force[id]+=_permForce[id];
+      _torque[id]+=_permTorque[id];
+    }
+  }
+  return;
+}
+
+void ForceContainer::reset(long iter, bool resetAll) {
+  memset(&_force [0],0,sizeof(Vector3r)*size);
+  memset(&_torque[0],0,sizeof(Vector3r)*size);
+  if(moveRotUsed){
+    memset(&_move  [0],0,sizeof(Vector3r)*size);
+    memset(&_rot   [0],0,sizeof(Vector3r)*size);
+    moveRotUsed=false;
+  }
+  if (resetAll){
+    memset(&_permForce [0], 0,sizeof(Vector3r)*size);
+    memset(&_permTorque[0], 0,sizeof(Vector3r)*size);
+    permForceUsed = false;
+  }
+  lastReset=iter;
+}
+
+void ForceContainer::resize(size_t newSize) {
+  _force.resize(newSize,Vector3r::Zero());
+  _torque.resize(newSize,Vector3r::Zero());
+  _permForce.resize(newSize,Vector3r::Zero());
+  _permTorque.resize(newSize,Vector3r::Zero());
+  _move.resize(newSize,Vector3r::Zero());
+  _rot.resize(newSize,Vector3r::Zero());
+  size=newSize;
+}
+
+const int ForceContainer::getNumAllocatedThreads() const {return 1;}
+const bool ForceContainer::getMoveRotUsed() const {return moveRotUsed;}
+const bool ForceContainer::getPermForceUsed() const {return permForceUsed;}
+#endif